From 5a6adba3e625f41ce30c974aa4836499e3c50c0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=85=8B=E4=BB=98?= Date: Sat, 4 Feb 2017 12:52:37 +0800 Subject: [PATCH 01/85] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=8B=B1=E8=AF=AD?= =?UTF-8?q?=E7=8E=AF=E5=A2=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/res/values-en/gallery_strings.xml | 20 +++++++++++++++++++ .../res/values-en/gallery_ucrop_strings.xml | 10 ++++++++++ 2 files changed, 30 insertions(+) create mode 100644 library/src/main/res/values-en/gallery_strings.xml create mode 100644 library/src/main/res/values-en/gallery_ucrop_strings.xml diff --git a/library/src/main/res/values-en/gallery_strings.xml b/library/src/main/res/values-en/gallery_strings.xml new file mode 100644 index 00000000..2221c386 --- /dev/null +++ b/library/src/main/res/values-en/gallery_strings.xml @@ -0,0 +1,20 @@ + + Load more + No more + Loading… + + Complete + Complete(%1$d/%2$d) + You can only choose %1$d photos + %1$d/%2$d + photos + video + App request to read your album + Absolutely empty + The device has no camera + Camera not available + preview + All pictures + All video + Photograph + diff --git a/library/src/main/res/values-en/gallery_ucrop_strings.xml b/library/src/main/res/values-en/gallery_ucrop_strings.xml new file mode 100644 index 00000000..0f086e6d --- /dev/null +++ b/library/src/main/res/values-en/gallery_ucrop_strings.xml @@ -0,0 +1,10 @@ + + + Original proportion + Cut + + Cut + + Both input and output Uri must be specified + Therefore, override color resource (ucrop_color_toolbar_widget) in your app to make it work on pre-L devices + From a1449a612d378ac99805ad701c720ba441a0f321 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=85=8B=E4=BB=98?= Date: Fri, 17 Feb 2017 11:33:31 +0800 Subject: [PATCH 02/85] =?UTF-8?q?=E5=8F=91=E5=B8=83=E6=96=B0=E5=BA=93?= =?UTF-8?q?=E5=88=B0jcenter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- library/build.gradle | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/library/build.gradle b/library/build.gradle index 122a80ae..591b6349 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -52,7 +52,7 @@ dependencies { //===================================upload jcenter================================================= def siteUrl = 'https://github.com/FinalTeam/RxGalleryFinal' def gitUrl = 'https://github.com/FinalTeam/RxGalleryFinal.git' -group = "cn.finalteam.rxgalleryfinal" +group = "com.mg.RxCustomizedImagePicker" install { repositories.mavenInstaller { @@ -61,7 +61,7 @@ install { packaging 'aar' // Add your description here - name 'RxGalleryFinal' + name 'RxCustomizedImagePicker' description = 'android gallery' url siteUrl @@ -74,9 +74,9 @@ install { } developers { developer { - id 'pengjianbo' - name 'pengjianbo' - email '172340021@qq.com' + id 'liukefu2050' + name 'liukefu2050' + email 'liukefu2050@sina.com' } } scm { @@ -109,15 +109,11 @@ bintray { configurations = ['archives'] pkg { repo = "maven" - name = "RxGalleryFinal" + name = "RxCustomizedImagePicker" + userOrg = 'mgice' websiteUrl = siteUrl vcsUrl = gitUrl licenses = ["Apache-2.0"] publish = true - version { - gpg { - passphrase = properties.getProperty("bintray.gpg.password") - } - } } } From 9fbc80c7796cba31ee0988b655037366ae749384 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=85=8B=E4=BB=98?= Date: Thu, 23 Feb 2017 13:02:36 +0800 Subject: [PATCH 03/85] upload to jcenter --- library/build.gradle | 120 ++++++++++++++++++++++++++++--------------- 1 file changed, 79 insertions(+), 41 deletions(-) diff --git a/library/build.gradle b/library/build.gradle index 591b6349..ff86ee1b 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -3,7 +3,7 @@ apply plugin: 'me.tatarka.retrolambda' apply plugin: 'com.github.dcendents.android-maven' apply plugin: "com.jfrog.bintray" -version = "0.0.3" + android { compileSdkVersion 24 @@ -50,53 +50,81 @@ dependencies { } //===================================upload jcenter================================================= -def siteUrl = 'https://github.com/FinalTeam/RxGalleryFinal' -def gitUrl = 'https://github.com/FinalTeam/RxGalleryFinal.git' -group = "com.mg.RxCustomizedImagePicker" - -install { - repositories.mavenInstaller { - pom { - project { - packaging 'aar' - - // Add your description here - name 'RxCustomizedImagePicker' - description = 'android gallery' - url siteUrl - - // Set your license - licenses { - license { - name 'The Apache Software License, Version 2.0' - url 'http://www.apache.org/licenses/LICENSE-2.0.txt' - } - } - developers { - developer { - id 'liukefu2050' - name 'liukefu2050' - email 'liukefu2050@sina.com' - } - } - scm { - connection gitUrl - developerConnection gitUrl - url siteUrl +def siteUrl = 'https://github.com/liukefu2050/RxGalleryFinal' +def gitUrl = 'https://github.com/liukefu2050/RxGalleryFinal.git' - } - } - } - } -} +group = "com.mg.RxCustomizedImagePicker" +version = "0.0.3" +project.archivesBaseName = "library" task sourcesJar(type: Jar) { from android.sourceSets.main.java.srcDirs classifier = 'sources' } +tasks.withType(JavaCompile) { + options.encoding = "UTF-8" +} +task javadoc(type: Javadoc) { + source = android.sourceSets.main.java.srcDirs + classpath += configurations.compile + classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) +} + +task javadocJar(type: Jar, dependsOn: javadoc) { + classifier = 'javadoc' + from javadoc.destinationDir +} + +javadoc { + options{ + encoding "UTF-8" + charSet 'UTF-8' + author true + version true + links "https://androiddoc.qiniudn.com/reference/" + title "RxCustomizedImagePicker 0.0.3" + } +} artifacts { archives sourcesJar + // archives javadocJar +} + +install { + repositories.mavenInstaller { + pom.project { + name "RxCustomizedImagePicker" + description "android gallery" + url siteUrl + inceptionYear '2017' + + packaging 'aar' + groupId "com.mg.RxCustomizedImagePicker" + artifactId "library" + version "0.0.3" + licenses { + license { + name 'The Apache Software License, Version 2.0' + url 'http://www.apache.org/licenses/LICENSE-2.0.txt' + distribution 'repo' + } + } + developers { + developer { + id "liukefu2020" + name "liukefu2020" + email "liukefu2050@sina.com" + } + } + scm { + connection gitUrl + developerConnection gitUrl + url siteUrl + } + + } + } } Properties properties = new Properties() @@ -110,10 +138,20 @@ bintray { pkg { repo = "maven" name = "RxCustomizedImagePicker" - userOrg = 'mgice' + userOrg = user websiteUrl = siteUrl vcsUrl = gitUrl licenses = ["Apache-2.0"] publish = true + version { + name = '0.0.3' + desc = 'android gallery' + released = new Date() + vcsTag = '0.0.3' + attributes = ['gradle-plugin': 'com.use.less:com.use.less.gradle:gradle-useless-plugin'] + gpg { + passphrase = properties.getProperty("bintray.gpg.password") + } + } } -} +}/**/ From 7a237cbc564b9e35e69906aad66e12808122ca67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=85=8B=E4=BB=98?= Date: Fri, 24 Feb 2017 21:14:43 +0800 Subject: [PATCH 04/85] language change --- library/build.gradle | 10 +++++----- .../rxgalleryfinal/ui/adapter/BucketAdapter.java | 2 +- .../main/res/layout/gallery_fragment_media_page.xml | 2 +- .../main/res/layout/gallery_fragment_media_preview.xml | 2 +- library/src/main/res/values-en/gallery_strings.xml | 2 ++ .../src/main/res/values-en/gallery_ucrop_strings.xml | 2 +- library/src/main/res/values/gallery_strings.xml | 2 ++ 7 files changed, 13 insertions(+), 9 deletions(-) diff --git a/library/build.gradle b/library/build.gradle index ff86ee1b..332e3302 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -54,7 +54,7 @@ def siteUrl = 'https://github.com/liukefu2050/RxGalleryFinal' def gitUrl = 'https://github.com/liukefu2050/RxGalleryFinal.git' group = "com.mg.RxCustomizedImagePicker" -version = "0.0.3" +version = "0.0.4" project.archivesBaseName = "library" task sourcesJar(type: Jar) { @@ -82,7 +82,7 @@ javadoc { author true version true links "https://androiddoc.qiniudn.com/reference/" - title "RxCustomizedImagePicker 0.0.3" + title "RxCustomizedImagePicker 0.0.4" } } @@ -102,7 +102,7 @@ install { packaging 'aar' groupId "com.mg.RxCustomizedImagePicker" artifactId "library" - version "0.0.3" + version "0.0.4" licenses { license { name 'The Apache Software License, Version 2.0' @@ -144,10 +144,10 @@ bintray { licenses = ["Apache-2.0"] publish = true version { - name = '0.0.3' + name = '0.0.4' desc = 'android gallery' released = new Date() - vcsTag = '0.0.3' + vcsTag = '0.0.4' attributes = ['gradle-plugin': 'com.use.less:com.use.less.gradle:gradle-useless-plugin'] gpg { passphrase = properties.getProperty("bintray.gpg.password") diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/adapter/BucketAdapter.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/adapter/BucketAdapter.java index 517895a3..baf2950a 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/adapter/BucketAdapter.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/adapter/BucketAdapter.java @@ -61,7 +61,7 @@ public void onBindViewHolder(BucketViewHolder holder, int position) { BucketBean bucketBean = mBucketList.get(position); String bucketName = bucketBean.getBucketName(); if(position != 0) { - SpannableString nameSpannable = new SpannableString(bucketName + "\n" + bucketBean.getImageCount() + "张"); + SpannableString nameSpannable = new SpannableString(bucketName + "\n" + bucketBean.getImageCount() + this.mContext.getString(R.string.gallery_image_unit)); nameSpannable.setSpan(new ForegroundColorSpan(Color.GRAY), bucketName.length(), nameSpannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); nameSpannable.setSpan(new RelativeSizeSpan(0.8f), bucketName.length(), nameSpannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); holder.mTvBucketName.setText(nameSpannable); diff --git a/library/src/main/res/layout/gallery_fragment_media_page.xml b/library/src/main/res/layout/gallery_fragment_media_page.xml index ab1b02f0..cd4566e1 100644 --- a/library/src/main/res/layout/gallery_fragment_media_page.xml +++ b/library/src/main/res/layout/gallery_fragment_media_page.xml @@ -26,7 +26,7 @@ android:layout_alignParentRight="true" android:layout_centerVertical="true" android:layout_margin="2dp" - android:text="选中"/> + android:text="@string/gallery_image_selected"/> \ No newline at end of file diff --git a/library/src/main/res/layout/gallery_fragment_media_preview.xml b/library/src/main/res/layout/gallery_fragment_media_preview.xml index 8022335c..8973f1e0 100644 --- a/library/src/main/res/layout/gallery_fragment_media_preview.xml +++ b/library/src/main/res/layout/gallery_fragment_media_preview.xml @@ -26,7 +26,7 @@ android:layout_alignParentRight="true" android:layout_centerVertical="true" android:layout_margin="2dp" - android:text="选中" + android:text="@string/gallery_image_selected" android:checked="true"/> diff --git a/library/src/main/res/values-en/gallery_strings.xml b/library/src/main/res/values-en/gallery_strings.xml index 2221c386..e7b354f6 100644 --- a/library/src/main/res/values-en/gallery_strings.xml +++ b/library/src/main/res/values-en/gallery_strings.xml @@ -17,4 +17,6 @@ All pictures All video Photograph + Selected + pictures diff --git a/library/src/main/res/values-en/gallery_ucrop_strings.xml b/library/src/main/res/values-en/gallery_ucrop_strings.xml index 0f086e6d..f5f9ccfd 100644 --- a/library/src/main/res/values-en/gallery_ucrop_strings.xml +++ b/library/src/main/res/values-en/gallery_ucrop_strings.xml @@ -1,6 +1,6 @@ - Original proportion + Default Cut Cut diff --git a/library/src/main/res/values/gallery_strings.xml b/library/src/main/res/values/gallery_strings.xml index 92be0ade..afba0306 100644 --- a/library/src/main/res/values/gallery_strings.xml +++ b/library/src/main/res/values/gallery_strings.xml @@ -17,4 +17,6 @@ 所有图片 所有视频 拍摄照片 + 选中 + From b3a7b0241f7133e87b8d77849ce591797a2c11a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=85=8B=E4=BB=98?= Date: Thu, 20 Apr 2017 09:11:31 +0800 Subject: [PATCH 05/85] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=9B=B4=E6=8E=A5?= =?UTF-8?q?=E8=B0=83=E7=94=A8=E7=9B=B8=E6=9C=BA=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../finalteam/rxgalleryfinal/Configuration.java | 10 +++++++++- .../finalteam/rxgalleryfinal/RxGalleryFinal.java | 8 ++++++++ .../ui/fragment/MediaGridFragment.java | 16 ++++++++++++++-- .../rxgalleryfinal/sample/MainActivity.java | 2 ++ 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/Configuration.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/Configuration.java index 7d9438e8..ea2d5bc2 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/Configuration.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/Configuration.java @@ -40,7 +40,7 @@ protected Configuration() { private int imageLoaderType; private int imageConfig; private boolean hideCamera; - + private boolean openCameraOnStart = false; //==========UCrop START========== //是否隐藏裁剪页面底部控制栏,默认显示 private boolean hideBottomControls; @@ -152,6 +152,14 @@ public void setHideCamera(boolean hideCamera) { this.hideCamera = hideCamera; } + public boolean isOpenCameraOnStart() { + return openCameraOnStart; + } + + public void setOpenCameraOnStart(boolean openCameraOnStart) { + this.openCameraOnStart = openCameraOnStart; + } + public AbsImageLoader getImageLoader() { AbsImageLoader imageLoader = null; switch (imageLoaderType){ diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/RxGalleryFinal.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/RxGalleryFinal.java index 352598de..208e747f 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/RxGalleryFinal.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/RxGalleryFinal.java @@ -131,6 +131,14 @@ public RxGalleryFinal hideCamera() { return this; } + /** + * 直接打开相机 + * @return + */ + public RxGalleryFinal openCameraOnStart() { + configuration.setOpenCameraOnStart(true); + return this; + } /** * set to true to hide the bottom controls (shown by default) * @param hide diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaGridFragment.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaGridFragment.java index 8971cf3e..f31ad6a6 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaGridFragment.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaGridFragment.java @@ -110,12 +110,13 @@ public class MediaGridFragment extends BaseFragment implements MediaGridView, Re private Subscription mSubscrMediaCheckChangeEvent; private Subscription mSubscrCloseMediaViewPageFragmentEvent; private Subscription mSubscrRequestStorageReadAccessPermissionEvent; - + private static boolean openCameraOnStart = false; public static MediaGridFragment newInstance(Configuration configuration) { MediaGridFragment fragment = new MediaGridFragment(); Bundle bundle = new Bundle(); bundle.putParcelable(EXTRA_CONFIGURATION, configuration); fragment.setArguments(bundle); + openCameraOnStart = configuration.isOpenCameraOnStart(); return fragment; } @@ -258,7 +259,9 @@ public void setTheme() { @Override protected void onFirstTimeLaunched() { - + if(openCameraOnStart){ + this.openCameraOnStart(); + } } @Override @@ -397,6 +400,15 @@ private void openCamera() { } } + public void openCameraOnStart(){ + if (!CameraUtils.hasCamera(getContext())) { + Toast.makeText(getContext(), R.string.gallery_device_no_camera_tips, Toast.LENGTH_SHORT).show(); + return; + } + + openCamera(); + } + @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); diff --git a/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/MainActivity.java b/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/MainActivity.java index e52aa1f2..14cace39 100644 --- a/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/MainActivity.java +++ b/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/MainActivity.java @@ -41,6 +41,7 @@ protected void onCreate(Bundle savedInstanceState) { .image() .radio() .crop() + .openCameraOnStart() .imageLoader(ImageLoaderType.GLIDE) .subscribe(new RxBusResultSubscriber() { @Override @@ -53,6 +54,7 @@ protected void onEvent(ImageRadioResultEvent imageRadioResultEvent) throws Excep RxGalleryFinal .with(MainActivity.this) .image() + .openCameraOnStart() .multiple() .maxSize(8) .imageLoader(ImageLoaderType.GLIDE) From fbb17ebbc2426fcfc3db00377e69cf22615e1b55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=85=8B=E4=BB=98?= Date: Thu, 20 Apr 2017 11:23:37 +0800 Subject: [PATCH 06/85] add 0.0.6 --- library/build.gradle | 10 +++++----- .../cn/finalteam/rxgalleryfinal/Configuration.java | 2 ++ .../finalteam/rxgalleryfinal/sample/MainActivity.java | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/library/build.gradle b/library/build.gradle index 332e3302..62b6ca6b 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -54,7 +54,7 @@ def siteUrl = 'https://github.com/liukefu2050/RxGalleryFinal' def gitUrl = 'https://github.com/liukefu2050/RxGalleryFinal.git' group = "com.mg.RxCustomizedImagePicker" -version = "0.0.4" +version = "0.0.6" project.archivesBaseName = "library" task sourcesJar(type: Jar) { @@ -82,7 +82,7 @@ javadoc { author true version true links "https://androiddoc.qiniudn.com/reference/" - title "RxCustomizedImagePicker 0.0.4" + title "RxCustomizedImagePicker 0.0.6" } } @@ -102,7 +102,7 @@ install { packaging 'aar' groupId "com.mg.RxCustomizedImagePicker" artifactId "library" - version "0.0.4" + version "0.0.6" licenses { license { name 'The Apache Software License, Version 2.0' @@ -144,10 +144,10 @@ bintray { licenses = ["Apache-2.0"] publish = true version { - name = '0.0.4' + name = '0.0.6' desc = 'android gallery' released = new Date() - vcsTag = '0.0.4' + vcsTag = '0.0.6' attributes = ['gradle-plugin': 'com.use.less:com.use.less.gradle:gradle-useless-plugin'] gpg { passphrase = properties.getProperty("bintray.gpg.password") diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/Configuration.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/Configuration.java index ea2d5bc2..8b4319c9 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/Configuration.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/Configuration.java @@ -90,6 +90,7 @@ protected Configuration(Parcel in) { imageLoaderType = in.readInt(); imageConfig = in.readInt(); hideCamera = in.readByte() != 0; + openCameraOnStart = in.readByte() != 0; } public static final Creator CREATOR = new Creator() { @@ -346,5 +347,6 @@ public void writeToParcel(Parcel parcel, int i) { parcel.writeInt(imageLoaderType); parcel.writeInt(imageConfig); parcel.writeByte((byte) (hideCamera ? 1 : 0)); + parcel.writeByte((byte) (openCameraOnStart ? 1 : 0)); } } diff --git a/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/MainActivity.java b/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/MainActivity.java index 14cace39..307e12ad 100644 --- a/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/MainActivity.java +++ b/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/MainActivity.java @@ -54,7 +54,7 @@ protected void onEvent(ImageRadioResultEvent imageRadioResultEvent) throws Excep RxGalleryFinal .with(MainActivity.this) .image() - .openCameraOnStart() + .multiple() .maxSize(8) .imageLoader(ImageLoaderType.GLIDE) From cf5074e65a9d659fd9a56be298a84297b03338b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=85=8B=E4=BB=98?= Date: Thu, 12 Oct 2017 09:53:29 +0800 Subject: [PATCH 07/85] =?UTF-8?q?=E8=BF=87=E6=BB=A4=E4=B8=B4=E6=97=B6?= =?UTF-8?q?=E7=9B=AE=E5=BD=95=EF=BC=8C=E5=A2=9E=E5=8A=A0=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E6=A0=87=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/finalteam/rxgalleryfinal/Configuration.java | 13 ++++++++++++- .../cn/finalteam/rxgalleryfinal/RxGalleryFinal.java | 8 ++++++++ .../rxgalleryfinal/ui/activity/BaseActivity.java | 5 +++++ .../rxgalleryfinal/ui/activity/MediaActivity.java | 4 +++- .../ui/fragment/MediaGridFragment.java | 8 ++------ .../finalteam/rxgalleryfinal/utils/MediaUtils.java | 3 +++ 6 files changed, 33 insertions(+), 8 deletions(-) diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/Configuration.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/Configuration.java index 8b4319c9..c7beb1b7 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/Configuration.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/Configuration.java @@ -67,7 +67,8 @@ protected Configuration() { private int maxResultHeight; //==========UCrop END========== - + //设置显示标题 + private String title = null; protected Configuration(Parcel in) { image = in.readByte() != 0; selectedList = in.createTypedArrayList(MediaBean.CREATOR); @@ -91,6 +92,7 @@ protected Configuration(Parcel in) { imageConfig = in.readInt(); hideCamera = in.readByte() != 0; openCameraOnStart = in.readByte() != 0; + title = in.readString(); } public static final Creator CREATOR = new Creator() { @@ -221,6 +223,14 @@ public void setCompressionQuality(int compressionQuality) { this.compressionQuality = compressionQuality; } + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + public void setAllowedGestures(@UCropActivity.GestureTypes int []gestures) { this.gestures = gestures; } @@ -348,5 +358,6 @@ public void writeToParcel(Parcel parcel, int i) { parcel.writeInt(imageConfig); parcel.writeByte((byte) (hideCamera ? 1 : 0)); parcel.writeByte((byte) (openCameraOnStart ? 1 : 0)); + parcel.writeString(title); } } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/RxGalleryFinal.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/RxGalleryFinal.java index 208e747f..9b2b2d92 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/RxGalleryFinal.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/RxGalleryFinal.java @@ -254,6 +254,14 @@ public RxGalleryFinal cropMaxResultSize(@IntRange(from = 100) int width, @IntRan return this; } + /** + * 设置显示标题 + * @return + */ + public RxGalleryFinal setTitle(String title) { + configuration.setTitle(title); + return this; + } /** * 设置回调 * @param rxBusResultSubscriber diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/activity/BaseActivity.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/activity/BaseActivity.java index d2bb3b05..098599de 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/activity/BaseActivity.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/activity/BaseActivity.java @@ -4,6 +4,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.Message; +import android.os.StrictMode; import android.support.annotation.LayoutRes; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; @@ -29,6 +30,10 @@ public abstract class BaseActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); + + StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder(); + StrictMode.setVmPolicy(builder.build()); + printActivityLife("onCreate"); Intent intent = getIntent(); Bundle bundle = null; diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/activity/MediaActivity.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/activity/MediaActivity.java index c5204829..20253718 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/activity/MediaActivity.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/activity/MediaActivity.java @@ -225,7 +225,9 @@ public void showMediaGridFragment() { ft.show(mMediaGridFragment) .commit(); - if(mConfiguration.isImage()) { + if(mConfiguration.getTitle()!=null){ + mTvToolbarTitle.setText(mConfiguration.getTitle()); + } else if(mConfiguration.isImage()) { mTvToolbarTitle.setText(R.string.gallery_media_grid_image_title); } else { mTvToolbarTitle.setText(R.string.gallery_media_grid_video_title); diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaGridFragment.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaGridFragment.java index f31ad6a6..a3cff496 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaGridFragment.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaGridFragment.java @@ -101,7 +101,6 @@ public class MediaGridFragment extends BaseFragment implements MediaGridView, Re private int mPage = 1; private File mImageStoreDir; - private File mImageStoreCropDir; private String mImagePath; private String mBucketId = String.valueOf(Integer.MIN_VALUE); @@ -126,11 +125,8 @@ public void onAttach(Context context) { if(context instanceof MediaActivity) { mMediaActivity = (MediaActivity) context; } + //临时目录 mImageStoreDir = new File(Environment.getExternalStorageDirectory(), "/DCIM/RxGalleryFinal/"); - mImageStoreCropDir = new File(mImageStoreDir, "crop"); - if (!mImageStoreCropDir.exists()) { - mImageStoreCropDir.mkdirs(); - } mMediaScanner = new MediaScanner(context); } @@ -376,7 +372,7 @@ private void radioNext(MediaBean mediaBean) { } else { String originalPath = mediaBean.getOriginalPath(); File file = new File(originalPath); - Uri outUri = Uri.fromFile(new File(mImageStoreCropDir, file.getName())); + Uri outUri = Uri.fromFile(new File(mImageStoreDir, file.getName())); Intent intent = new Intent(getContext(), UCropActivity.class); Bundle bundle = new Bundle(); bundle.putParcelable(UCropActivity.EXTRA_OUTPUT_URI, outUri); diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaUtils.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaUtils.java index 990af20a..f49f7e18 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaUtils.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaUtils.java @@ -375,6 +375,9 @@ public static List getAllBucket(Context context, boolean isImage) { bucketId = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_ID)); bucketBean.setBucketId(bucketId); String bucketDisplayName = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME)); + if("RxGalleryFinal".equals(bucketDisplayName)){ + continue; + } bucketBean.setBucketName(bucketDisplayName); bucketKey = MediaStore.Images.Media.BUCKET_ID; cover = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA)); From 2619db609b90c67dd3fa5d5c6dae8d9e80dcf045 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=85=8B=E4=BB=98?= Date: Thu, 12 Oct 2017 10:41:33 +0800 Subject: [PATCH 08/85] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=8B=8D=E7=85=A7?= =?UTF-8?q?=E5=90=8E=E7=9B=B4=E6=8E=A5=E8=BF=94=E5=9B=9E=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../finalteam/rxgalleryfinal/Configuration.java | 11 +++++++++++ .../finalteam/rxgalleryfinal/RxGalleryFinal.java | 9 +++++++++ .../ui/fragment/MediaGridFragment.java | 16 ++++++++++++++-- .../rxgalleryfinal/sample/MainActivity.java | 4 +++- 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/Configuration.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/Configuration.java index c7beb1b7..b9592896 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/Configuration.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/Configuration.java @@ -41,6 +41,7 @@ protected Configuration() { private int imageConfig; private boolean hideCamera; private boolean openCameraOnStart = false; + private boolean returnAfterShot = false; //==========UCrop START========== //是否隐藏裁剪页面底部控制栏,默认显示 private boolean hideBottomControls; @@ -93,6 +94,7 @@ protected Configuration(Parcel in) { hideCamera = in.readByte() != 0; openCameraOnStart = in.readByte() != 0; title = in.readString(); + returnAfterShot = in.readByte() != 0; } public static final Creator CREATOR = new Creator() { @@ -163,6 +165,14 @@ public void setOpenCameraOnStart(boolean openCameraOnStart) { this.openCameraOnStart = openCameraOnStart; } + public boolean isReturnAfterShot() { + return returnAfterShot; + } + + public void setReturnAfterShot(boolean returnAfterShot) { + this.returnAfterShot = returnAfterShot; + } + public AbsImageLoader getImageLoader() { AbsImageLoader imageLoader = null; switch (imageLoaderType){ @@ -359,5 +369,6 @@ public void writeToParcel(Parcel parcel, int i) { parcel.writeByte((byte) (hideCamera ? 1 : 0)); parcel.writeByte((byte) (openCameraOnStart ? 1 : 0)); parcel.writeString(title); + parcel.writeByte((byte) (returnAfterShot ? 1 : 0)); } } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/RxGalleryFinal.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/RxGalleryFinal.java index 9b2b2d92..f0c1991b 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/RxGalleryFinal.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/RxGalleryFinal.java @@ -139,6 +139,15 @@ public RxGalleryFinal openCameraOnStart() { configuration.setOpenCameraOnStart(true); return this; } + + /** + * 拍摄后,直接返回图片 + * @return + */ + public RxGalleryFinal returnAfterShot() { + configuration.setReturnAfterShot(true); + return this; + } /** * set to true to hide the bottom controls (shown by default) * @param hide diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaGridFragment.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaGridFragment.java index a3cff496..4d1fbd96 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaGridFragment.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaGridFragment.java @@ -39,7 +39,9 @@ import cn.finalteam.rxgalleryfinal.presenter.impl.MediaGridPresenterImpl; import cn.finalteam.rxgalleryfinal.rxbus.RxBus; import cn.finalteam.rxgalleryfinal.rxbus.RxBusSubscriber; +import cn.finalteam.rxgalleryfinal.rxbus.event.BaseResultEvent; import cn.finalteam.rxgalleryfinal.rxbus.event.CloseMediaViewPageFragmentEvent; +import cn.finalteam.rxgalleryfinal.rxbus.event.ImageMultipleResultEvent; import cn.finalteam.rxgalleryfinal.rxbus.event.ImageRadioResultEvent; import cn.finalteam.rxgalleryfinal.rxbus.event.MediaCheckChangeEvent; import cn.finalteam.rxgalleryfinal.rxbus.event.OpenMediaPreviewFragmentEvent; @@ -110,12 +112,14 @@ public class MediaGridFragment extends BaseFragment implements MediaGridView, Re private Subscription mSubscrCloseMediaViewPageFragmentEvent; private Subscription mSubscrRequestStorageReadAccessPermissionEvent; private static boolean openCameraOnStart = false; + private static boolean returnAfterShot = false; public static MediaGridFragment newInstance(Configuration configuration) { MediaGridFragment fragment = new MediaGridFragment(); Bundle bundle = new Bundle(); bundle.putParcelable(EXTRA_CONFIGURATION, configuration); fragment.setArguments(bundle); openCameraOnStart = configuration.isOpenCameraOnStart(); + returnAfterShot = configuration.isReturnAfterShot(); return fragment; } @@ -512,8 +516,16 @@ public void onError(Throwable e) { public void onNext(MediaBean mediaBean) { if(!isDetached() && mediaBean != null) { - mMediaBeanList.add(1, mediaBean); - mMediaGridAdapter.notifyDataSetChanged(); + if(returnAfterShot){ + ArrayList list = new ArrayList<>(); + list.add(mediaBean); + BaseResultEvent event = new ImageMultipleResultEvent(list); + RxBus.getDefault().post(event); + getActivity().finish(); + }else{ + mMediaBeanList.add(1, mediaBean); + mMediaGridAdapter.notifyDataSetChanged(); + } } } diff --git a/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/MainActivity.java b/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/MainActivity.java index 307e12ad..f8436be4 100644 --- a/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/MainActivity.java +++ b/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/MainActivity.java @@ -42,6 +42,8 @@ protected void onCreate(Bundle savedInstanceState) { .radio() .crop() .openCameraOnStart() + .setTitle("标题你设置") + .returnAfterShot() .imageLoader(ImageLoaderType.GLIDE) .subscribe(new RxBusResultSubscriber() { @Override @@ -54,7 +56,7 @@ protected void onEvent(ImageRadioResultEvent imageRadioResultEvent) throws Excep RxGalleryFinal .with(MainActivity.this) .image() - + .setTitle("标题你设置") .multiple() .maxSize(8) .imageLoader(ImageLoaderType.GLIDE) From 74dc167b23b3f355350f0e0c7b438adb67657fb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=85=8B=E4=BB=98?= Date: Thu, 12 Oct 2017 10:47:12 +0800 Subject: [PATCH 09/85] =?UTF-8?q?=E5=A2=9E=E5=8A=A0jcenter=E6=96=B0?= =?UTF-8?q?=E7=89=88=E6=9C=AC0.0.7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- library/build.gradle | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/build.gradle b/library/build.gradle index 62b6ca6b..bf3e2fdc 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -54,7 +54,7 @@ def siteUrl = 'https://github.com/liukefu2050/RxGalleryFinal' def gitUrl = 'https://github.com/liukefu2050/RxGalleryFinal.git' group = "com.mg.RxCustomizedImagePicker" -version = "0.0.6" +version = "0.0.7" project.archivesBaseName = "library" task sourcesJar(type: Jar) { @@ -82,7 +82,7 @@ javadoc { author true version true links "https://androiddoc.qiniudn.com/reference/" - title "RxCustomizedImagePicker 0.0.6" + title "RxCustomizedImagePicker 0.0.7" } } @@ -102,7 +102,7 @@ install { packaging 'aar' groupId "com.mg.RxCustomizedImagePicker" artifactId "library" - version "0.0.6" + version "0.0.7" licenses { license { name 'The Apache Software License, Version 2.0' @@ -144,10 +144,10 @@ bintray { licenses = ["Apache-2.0"] publish = true version { - name = '0.0.6' + name = '0.0.7' desc = 'android gallery' released = new Date() - vcsTag = '0.0.6' + vcsTag = '0.0.7' attributes = ['gradle-plugin': 'com.use.less:com.use.less.gradle:gradle-useless-plugin'] gpg { passphrase = properties.getProperty("bintray.gpg.password") From 11163508108b2e4a4f9da85c9a0c8b51bf5442ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=85=8B=E4=BB=98?= Date: Wed, 25 Oct 2017 15:46:15 +0800 Subject: [PATCH 10/85] remove ucorp --- library/build.gradle | 1 + .../rxgalleryfinal/Configuration.java | 2 +- .../ui/fragment/MediaGridFragment.java | 17 +- .../com/yalantis/ucrop/UCropActivity.java | 620 ----------------- .../ucrop/callback/BitmapCropCallback.java | 12 - .../ucrop/callback/BitmapLoadCallback.java | 15 - .../callback/CropBoundsChangeListener.java | 10 - .../callback/OverlayViewChangeListener.java | 12 - .../com/yalantis/ucrop/model/AspectRatio.java | 66 -- .../yalantis/ucrop/model/CropParameters.java | 58 -- .../com/yalantis/ucrop/model/ExifInfo.java | 63 -- .../com/yalantis/ucrop/model/ImageState.java | 37 -- .../yalantis/ucrop/task/BitmapCropTask.java | 190 ------ .../yalantis/ucrop/task/BitmapLoadTask.java | 214 ------ .../yalantis/ucrop/util/BitmapLoadUtils.java | 159 ----- .../com/yalantis/ucrop/util/CubicEasing.java | 17 - .../ucrop/util/FastBitmapDrawable.java | 103 --- .../com/yalantis/ucrop/util/FileUtils.java | 537 --------------- .../ucrop/util/ImageHeaderParser.java | 420 ------------ .../com/yalantis/ucrop/util/RectUtils.java | 72 -- .../ucrop/util/RotationGestureDetector.java | 111 ---- .../ucrop/util/SelectedStateListDrawable.java | 42 -- .../yalantis/ucrop/view/CropImageView.java | 622 ------------------ .../ucrop/view/GestureCropImageView.java | 152 ----- .../com/yalantis/ucrop/view/OverlayView.java | 485 -------------- .../ucrop/view/TransformImageView.java | 338 ---------- .../com/yalantis/ucrop/view/UCropView.java | 53 -- .../view/widget/AspectRatioTextView.java | 164 ----- .../widget/HorizontalProgressWheelView.java | 152 ----- .../rxgalleryfinal/sample/MainActivity.java | 2 +- 30 files changed, 17 insertions(+), 4729 deletions(-) delete mode 100755 library/src/main/java/com/yalantis/ucrop/UCropActivity.java delete mode 100755 library/src/main/java/com/yalantis/ucrop/callback/BitmapCropCallback.java delete mode 100755 library/src/main/java/com/yalantis/ucrop/callback/BitmapLoadCallback.java delete mode 100755 library/src/main/java/com/yalantis/ucrop/callback/CropBoundsChangeListener.java delete mode 100755 library/src/main/java/com/yalantis/ucrop/callback/OverlayViewChangeListener.java delete mode 100755 library/src/main/java/com/yalantis/ucrop/model/AspectRatio.java delete mode 100755 library/src/main/java/com/yalantis/ucrop/model/CropParameters.java delete mode 100755 library/src/main/java/com/yalantis/ucrop/model/ExifInfo.java delete mode 100755 library/src/main/java/com/yalantis/ucrop/model/ImageState.java delete mode 100755 library/src/main/java/com/yalantis/ucrop/task/BitmapCropTask.java delete mode 100755 library/src/main/java/com/yalantis/ucrop/task/BitmapLoadTask.java delete mode 100755 library/src/main/java/com/yalantis/ucrop/util/BitmapLoadUtils.java delete mode 100755 library/src/main/java/com/yalantis/ucrop/util/CubicEasing.java delete mode 100755 library/src/main/java/com/yalantis/ucrop/util/FastBitmapDrawable.java delete mode 100755 library/src/main/java/com/yalantis/ucrop/util/FileUtils.java delete mode 100755 library/src/main/java/com/yalantis/ucrop/util/ImageHeaderParser.java delete mode 100755 library/src/main/java/com/yalantis/ucrop/util/RectUtils.java delete mode 100755 library/src/main/java/com/yalantis/ucrop/util/RotationGestureDetector.java delete mode 100755 library/src/main/java/com/yalantis/ucrop/util/SelectedStateListDrawable.java delete mode 100755 library/src/main/java/com/yalantis/ucrop/view/CropImageView.java delete mode 100755 library/src/main/java/com/yalantis/ucrop/view/GestureCropImageView.java delete mode 100755 library/src/main/java/com/yalantis/ucrop/view/OverlayView.java delete mode 100755 library/src/main/java/com/yalantis/ucrop/view/TransformImageView.java delete mode 100755 library/src/main/java/com/yalantis/ucrop/view/UCropView.java delete mode 100755 library/src/main/java/com/yalantis/ucrop/view/widget/AspectRatioTextView.java delete mode 100755 library/src/main/java/com/yalantis/ucrop/view/widget/HorizontalProgressWheelView.java diff --git a/library/build.gradle b/library/build.gradle index bf3e2fdc..ab9aa375 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -42,6 +42,7 @@ dependencies { compile 'io.reactivex:rxjava:1.1.9' compile 'com.android.support:recyclerview-v7:24.2.0' compile 'com.android.support:appcompat-v7:24.2.0' + compile 'com.yalantis:ucrop:2.2.0' provided 'com.squareup.picasso:picasso:2.5.2' provided 'com.facebook.fresco:fresco:0.12.0' diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/Configuration.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/Configuration.java index b9592896..d896a6f6 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/Configuration.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/Configuration.java @@ -63,7 +63,7 @@ protected Configuration() { //是否允许改变裁剪大小 private boolean freestyleCropEnabled = OverlayView.DEFAULT_FREESTYLE_CROP_ENABLED; //是否显示裁剪框半透明椭圆浮层 - private boolean ovalDimmedLayer = OverlayView.DEFAULT_OVAL_DIMMED_LAYER; + private boolean ovalDimmedLayer = OverlayView.DEFAULT_CIRCLE_DIMMED_LAYER; private int maxResultWidth; private int maxResultHeight; diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaGridFragment.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaGridFragment.java index 4d1fbd96..ed121220 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaGridFragment.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaGridFragment.java @@ -19,6 +19,7 @@ import android.widget.TextView; import android.widget.Toast; +import com.yalantis.ucrop.UCrop; import com.yalantis.ucrop.UCropActivity; import java.io.File; @@ -379,9 +380,19 @@ private void radioNext(MediaBean mediaBean) { Uri outUri = Uri.fromFile(new File(mImageStoreDir, file.getName())); Intent intent = new Intent(getContext(), UCropActivity.class); Bundle bundle = new Bundle(); - bundle.putParcelable(UCropActivity.EXTRA_OUTPUT_URI, outUri); - bundle.putParcelable(UCropActivity.EXTRA_INPUT_BEAN, mediaBean); - bundle.putParcelable(UCropActivity.EXTRA_CONFIGURATION, mConfiguration); + bundle.putParcelable(UCrop.EXTRA_OUTPUT_URI, outUri); + bundle.putParcelable(UCrop.Options.EXTRA_ASPECT_RATIO_OPTIONS, mediaBean); + bundle.putBoolean(UCrop.Options.EXTRA_HIDE_BOTTOM_CONTROLS, mConfiguration.isHideBottomControls()); + bundle.putIntArray(UCrop.Options.EXTRA_ALLOWED_GESTURES, mConfiguration.getAllowedGestures()); + bundle.putInt(UCrop.Options.EXTRA_COMPRESSION_QUALITY, mConfiguration.getCompressionQuality()); + bundle.putInt(UCrop.Options.EXTRA_MAX_BITMAP_SIZE, mConfiguration.getMaxBitmapSize()); + bundle.putFloat(UCrop.Options.EXTRA_MAX_SCALE_MULTIPLIER, mConfiguration.getMaxScaleMultiplier()); + bundle.putFloat(UCrop.EXTRA_ASPECT_RATIO_X, mConfiguration.getAspectRatioX()); + bundle.putFloat(UCrop.EXTRA_ASPECT_RATIO_Y, mConfiguration.getAspectRatioY()); + bundle.putInt(UCrop.EXTRA_MAX_SIZE_X, mConfiguration.getMaxResultWidth()); + bundle.putInt(UCrop.EXTRA_MAX_SIZE_Y, mConfiguration.getMaxResultHeight()); + bundle.putInt(UCrop.Options.EXTRA_ASPECT_RATIO_SELECTED_BY_DEFAULT, mConfiguration.getSelectedByDefault()); + bundle.putBoolean(UCrop.Options.EXTRA_FREE_STYLE_CROP, mConfiguration.isFreestyleCropEnabled()); intent.putExtras(bundle); startActivity(intent); } diff --git a/library/src/main/java/com/yalantis/ucrop/UCropActivity.java b/library/src/main/java/com/yalantis/ucrop/UCropActivity.java deleted file mode 100755 index ce998ab9..00000000 --- a/library/src/main/java/com/yalantis/ucrop/UCropActivity.java +++ /dev/null @@ -1,620 +0,0 @@ -package com.yalantis.ucrop; - -import android.graphics.Bitmap; -import android.graphics.PorterDuff; -import android.graphics.drawable.Animatable; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.Bundle; -import android.support.annotation.IdRes; -import android.support.annotation.IntDef; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.app.ActionBar; -import android.support.v7.widget.Toolbar; -import android.text.TextUtils; -import android.util.TypedValue; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.view.animation.AccelerateInterpolator; -import android.widget.FrameLayout; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.RelativeLayout; -import android.widget.TextView; - -import com.yalantis.ucrop.callback.BitmapCropCallback; -import com.yalantis.ucrop.model.AspectRatio; -import com.yalantis.ucrop.util.SelectedStateListDrawable; -import com.yalantis.ucrop.view.CropImageView; -import com.yalantis.ucrop.view.GestureCropImageView; -import com.yalantis.ucrop.view.OverlayView; -import com.yalantis.ucrop.view.TransformImageView; -import com.yalantis.ucrop.view.UCropView; -import com.yalantis.ucrop.view.widget.AspectRatioTextView; -import com.yalantis.ucrop.view.widget.HorizontalProgressWheelView; - -import java.io.File; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - -import cn.finalteam.rxgalleryfinal.R; -import cn.finalteam.rxgalleryfinal.bean.ImageCropBean; -import cn.finalteam.rxgalleryfinal.bean.MediaBean; -import cn.finalteam.rxgalleryfinal.rxbus.RxBus; -import cn.finalteam.rxgalleryfinal.rxbus.event.BaseResultEvent; -import cn.finalteam.rxgalleryfinal.rxbus.event.CloseRxMediaGridPageEvent; -import cn.finalteam.rxgalleryfinal.rxbus.event.ImageRadioResultEvent; -import cn.finalteam.rxgalleryfinal.ui.activity.BaseActivity; -import cn.finalteam.rxgalleryfinal.utils.FilenameUtils; -import cn.finalteam.rxgalleryfinal.utils.Logger; -import cn.finalteam.rxgalleryfinal.utils.OsCompat; -import cn.finalteam.rxgalleryfinal.utils.ThemeUtils; - -/** - * Created by Oleksii Shliama (https://github.com/shliama).//b2b7690 - */ - -@SuppressWarnings("ConstantConditions") -public class UCropActivity extends BaseActivity { - - public static final String EXTRA_INPUT_BEAN = EXTRA_PREFIX + ".InputBean"; - public static final String EXTRA_OUTPUT_URI = EXTRA_PREFIX + ".OutputUri"; - - public static final int DEFAULT_COMPRESS_QUALITY = 90; - - public static final int NONE = 0; - public static final int SCALE = 1; - public static final int ROTATE = 2; - public static final int ALL = 3; - - @IntDef({NONE, SCALE, ROTATE, ALL}) - @Retention(RetentionPolicy.SOURCE) - public @interface GestureTypes { - } - - private static final int TABS_COUNT = 3; - private static final int SCALE_WIDGET_SENSITIVITY_COEFFICIENT = 15000; - private static final int ROTATE_WIDGET_SENSITIVITY_COEFFICIENT = 42; - - private int mActiveWidgetColor; - private int mToolbarWidgetColor; - - private boolean mShowBottomControls; - private boolean mShowLoader = true; - - private UCropView mUCropView; - private GestureCropImageView mGestureCropImageView; - private OverlayView mOverlayView; - private ViewGroup mWrapperStateAspectRatio, mWrapperStateRotate, mWrapperStateScale; - private ViewGroup mLayoutAspectRatio, mLayoutRotate, mLayoutScale; - private List mCropAspectRatioViews = new ArrayList<>(); - private TextView mTextViewRotateAngle, mTextViewScalePercent; - private View mBlockingView; - private Toolbar mToolbar; - private ImageView mStateScaleImageView; - private ImageView mStateRotateImageView; - private ImageView mStateAspectRatioImageView; - private TextView mTvToolbarTitle; - private FrameLayout mUcropFrame; - - private Bitmap.CompressFormat mCompressFormat = Bitmap.CompressFormat.JPEG; - private int mCompressQuality = DEFAULT_COMPRESS_QUALITY; - private int[] mAllowedGestures = new int[]{SCALE, ROTATE, ALL}; - private MediaBean mMediaBean; - private View mToolbarDivider; - - @Override - public int getContentView() { - return R.layout.gallery_ucrop_activity_photobox; - } - - @Override - protected void onCreateOk(@Nullable Bundle savedInstanceState) { - setupViews(); - setImageData(savedInstanceState); - setInitialState(); - addBlockingView(); - - mGestureCropImageView.setTransformImageListener(mImageListener); - } - - @Override - public void findViews(){ - mToolbar = (Toolbar) findViewById(R.id.toolbar); - mTvToolbarTitle = (TextView) findViewById(R.id.tv_toolbar_title); - ViewGroup photoBox = (ViewGroup) findViewById(R.id.ucrop_photobox); - View.inflate(this, R.layout.gallery_ucrop_controls, photoBox); - mWrapperStateAspectRatio = (ViewGroup) findViewById(R.id.state_aspect_ratio); - mWrapperStateAspectRatio.setOnClickListener(mStateClickListener); - mWrapperStateRotate = (ViewGroup) findViewById(R.id.state_rotate); - mWrapperStateRotate.setOnClickListener(mStateClickListener); - mWrapperStateScale = (ViewGroup) findViewById(R.id.state_scale); - mWrapperStateScale.setOnClickListener(mStateClickListener); - - mLayoutAspectRatio = (ViewGroup) findViewById(R.id.layout_aspect_ratio); - mLayoutRotate = (ViewGroup) findViewById(R.id.layout_rotate_wheel); - mLayoutScale = (ViewGroup) findViewById(R.id.layout_scale_wheel); - - mUCropView = (UCropView) findViewById(R.id.ucrop); - - mStateScaleImageView = (ImageView) findViewById(R.id.image_view_state_scale); - mStateRotateImageView = (ImageView) findViewById(R.id.image_view_state_rotate); - mStateAspectRatioImageView = (ImageView) findViewById(R.id.image_view_state_aspect_ratio); - - mTextViewRotateAngle = ((TextView) findViewById(R.id.text_view_rotate)); - - mGestureCropImageView = mUCropView.getCropImageView(); - mOverlayView = mUCropView.getOverlayView(); - mUcropFrame = (FrameLayout) findViewById(R.id.ucrop_frame); - mToolbarDivider = findViewById(R.id.toolbar_divider); - } - - @Override - protected void setTheme() { - mActiveWidgetColor = ThemeUtils.resolveColor(this, R.attr.gallery_color_active_widget, R.color.gallery_default_ucrop_color_widget_active); - mToolbarWidgetColor = ThemeUtils.resolveColor(this, R.attr.gallery_toolbar_widget_color, R.color.gallery_default_color_toolbar_icon); - - mStateScaleImageView.setImageDrawable(new SelectedStateListDrawable(mStateScaleImageView.getDrawable(), mActiveWidgetColor)); - mStateRotateImageView.setImageDrawable(new SelectedStateListDrawable(mStateRotateImageView.getDrawable(), mActiveWidgetColor)); - mStateAspectRatioImageView.setImageDrawable(new SelectedStateListDrawable(mStateAspectRatioImageView.getDrawable(), mActiveWidgetColor)); - - int statusBarColor = ThemeUtils.resolveColor(this, R.attr.gallery_color_statusbar, R.color.gallery_default_color_statusbar); - ThemeUtils.setStatusBarColor(statusBarColor, getWindow()); - - Drawable closeDrawable = ThemeUtils.resolveDrawable(this, R.attr.gallery_toolbar_close_image, R.drawable.gallery_default_toolbar_close_image); - int closeColor = ThemeUtils.resolveColor(this, R.attr.gallery_toolbar_close_color, R.color.gallery_default_toolbar_widget_color); - closeDrawable.setColorFilter(closeColor, PorterDuff.Mode.SRC_ATOP); - mToolbar.setNavigationIcon(closeDrawable); - - float titleTextSize = ThemeUtils.resolveDimen(this, R.attr.gallery_toolbar_text_size, R.dimen.gallery_default_toolbar_text_size); - mTvToolbarTitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, titleTextSize); - int titleTextColor = ThemeUtils.resolveColor(this, R.attr.gallery_toolbar_text_color, R.color.gallery_default_toolbar_text_color); - mTvToolbarTitle.setTextColor(titleTextColor); - mTvToolbarTitle.setText(ThemeUtils.resolveString(this, R.attr.gallery_ucrop_title_text, R.string.gallery_ucrop_menu_crop)); - mToolbar.setTitleTextColor(titleTextColor); - - int toolbarBg = ThemeUtils.resolveColor(this, R.attr.gallery_toolbar_bg, R.color.gallery_default_color_toolbar_bg); - mToolbar.setBackgroundColor(toolbarBg); - int toolbarHeight = (int) ThemeUtils.resolveDimen(this, R.attr.gallery_toolbar_height, R.dimen.gallery_default_toolbar_height); - mToolbar.setMinimumHeight(toolbarHeight); - - int gravity = ThemeUtils.resolveInteger(this, R.attr.gallery_toolbar_text_gravity, R.integer.gallery_default_toolbar_text_gravity); - mTvToolbarTitle.setLayoutParams(new Toolbar.LayoutParams(Toolbar.LayoutParams.WRAP_CONTENT, Toolbar.LayoutParams.WRAP_CONTENT, gravity)); - - setSupportActionBar(mToolbar); - final ActionBar actionBar = getSupportActionBar(); - if (actionBar != null) { - actionBar.setDisplayShowTitleEnabled(false); - } - - mOverlayView.setDimmedColor(ThemeUtils.resolveColor(this, R.attr.gallery_ucrop_image_outer_frame_bg, R.color.gallery_default_ucrop_color_default_dimmed)); - mOverlayView.setCropFrameColor(ThemeUtils.resolveColor(this, R.attr.gallery_ucrop_crop_frame_color, R.color.gallery_default_ucrop_color_default_crop_frame)); - mOverlayView.setCropFrameStrokeWidth((int)ThemeUtils.resolveDimen(this, R.attr.gallery_ucrop_crop_frame_stroke_width, R.dimen.gallery_ucrop_default_crop_frame_stroke_width)); - mOverlayView.setCropGridColor(ThemeUtils.resolveColor(this, R.attr.gallery_ucrop_image_grid_color, R.color.gallery_default_ucrop_color_default_crop_grid)); - mOverlayView.setCropGridStrokeWidth((int)ThemeUtils.resolveDimen(this, R.attr.gallery_ucrop_image_grid_stroke_size, R.dimen.gallery_ucrop_default_crop_grid_stroke_width)); - mUcropFrame.setBackgroundColor(ThemeUtils.resolveColor(this, R.attr.gallery_ucrop_color_crop_background, R.color.gallery_default_ucrop_color_crop_background)); - - int dividerHeight = (int) ThemeUtils.resolveDimen(this, R.attr.gallery_toolbar_divider_height, R.dimen.gallery_default_toolbar_divider_height); - int dividerBottomMargin = (int) ThemeUtils.resolveDimen(this, R.attr.gallery_toolbar_bottom_margin, R.dimen.gallery_default_toolbar_bottom_margin); - LinearLayout.LayoutParams dividerLP = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, dividerHeight); - dividerLP.bottomMargin = dividerBottomMargin; - mToolbarDivider.setLayoutParams(dividerLP); - - Drawable dividerDrawable = ThemeUtils.resolveDrawable(this, R.attr.gallery_toolbar_divider_bg, R.color.gallery_default_toolbar_divider_bg); - OsCompat.setBackgroundDrawableCompat(mToolbarDivider, dividerDrawable); - } - - @Override - public boolean onCreateOptionsMenu(final Menu menu) { - getMenuInflater().inflate(R.menu.gallery_ucrop_menu_activity, menu); - - // Change crop & loader menu icons color to match the rest of the UI colors - - MenuItem menuItemLoader = menu.findItem(R.id.menu_loader); - Drawable menuItemLoaderIcon = menuItemLoader.getIcon(); - if (menuItemLoaderIcon != null) { - try { - menuItemLoaderIcon.mutate(); - menuItemLoaderIcon.setColorFilter(mToolbarWidgetColor, PorterDuff.Mode.SRC_ATOP); - menuItemLoader.setIcon(menuItemLoaderIcon); - } catch (IllegalStateException e) { - Logger.e(String.format("%s - %s", e.getMessage(), getString(R.string.gallery_ucrop_mutate_exception_hint))); - } - ((Animatable) menuItemLoader.getIcon()).start(); - } - - MenuItem menuItemCrop = menu.findItem(R.id.menu_crop); - Drawable menuItemCropIcon = menuItemCrop.getIcon(); - if (menuItemCropIcon != null) { - menuItemCropIcon.mutate(); - menuItemCropIcon.setColorFilter(mToolbarWidgetColor, PorterDuff.Mode.SRC_ATOP); - menuItemCrop.setIcon(menuItemCropIcon); - } - - return true; - } - - @Override - public boolean onPrepareOptionsMenu(Menu menu) { - menu.findItem(R.id.menu_crop).setVisible(!mShowLoader); - menu.findItem(R.id.menu_loader).setVisible(mShowLoader); - return super.onPrepareOptionsMenu(menu); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == R.id.menu_crop) { - cropAndSaveImage(); - } else if (item.getItemId() == android.R.id.home) { - onBackPressed(); - } - return super.onOptionsItemSelected(item); - } - - @Override - protected void onStop() { - super.onStop(); - if (mGestureCropImageView != null) { - mGestureCropImageView.cancelAllAnimations(); - } - } - - /** - * This method extracts all data from the incoming intent and setups views properly. - */ - private void setImageData(@NonNull Bundle savedInstanceState) { - mMediaBean = savedInstanceState.getParcelable(EXTRA_INPUT_BEAN); - - File file = new File(mMediaBean.getOriginalPath()); - Uri inputUri = Uri.fromFile(file); - Uri outputUri = savedInstanceState.getParcelable(EXTRA_OUTPUT_URI); - - processOptions(); - - if (inputUri != null && outputUri != null) { - try { - mGestureCropImageView.setImageUri(inputUri, outputUri); - } catch (Exception e) { - setResultError(e); - } - } else { - setResultError(new NullPointerException(getString(R.string.gallery_ucrop_error_input_data_is_absent))); - } - } - - @SuppressWarnings("deprecation") - private void processOptions() { - // Bitmap compression options - String ext = FilenameUtils.getExtension(mMediaBean.getOriginalPath()); - mCompressFormat = Bitmap.CompressFormat.JPEG; - if (ext != null && TextUtils.equals(ext.toLowerCase(), "png")) { - mCompressFormat = Bitmap.CompressFormat.PNG; - } else if (ext != null && TextUtils.equals(ext.toLowerCase(), "webp")) { - mCompressFormat = Bitmap.CompressFormat.WEBP; - } - - mCompressQuality = mConfiguration.getCompressionQuality(); - - // Gestures options - int[] allowedGestures = mConfiguration.getAllowedGestures(); - if (allowedGestures != null && allowedGestures.length == TABS_COUNT) { - mAllowedGestures = allowedGestures; - } - - // Crop image view options - mGestureCropImageView.setMaxBitmapSize(mConfiguration.getMaxBitmapSize()); - mGestureCropImageView.setMaxScaleMultiplier(mConfiguration.getMaxScaleMultiplier()); - mGestureCropImageView.setImageToWrapCropBoundsAnimDuration(CropImageView.DEFAULT_IMAGE_TO_CROP_BOUNDS_ANIM_DURATION); - - // Overlay view options -// boolean freeStyleCrop = ThemeUtils.resolveBoolean(this, R.attr.gallery_ucrop_free_style_crop, R.bool.gallery_default_ucrop_free_style_crop); - mOverlayView.setFreestyleCropEnabled(mConfiguration.isFreestyleCropEnabled()); -// boolean ovalDimmedLayer = ThemeUtils.resolveBoolean(this, R.attr.gallery_ucrop_oval_dimmed_layer_enabled, R.bool.gallery_default_ucrop_oval_dimmed_layer_enabled); -// mOverlayView.setOvalDimmedLayer(ovalDimmedLayer); - mOverlayView.setOvalDimmedLayer(mConfiguration.isOvalDimmedLayer()); - boolean showCropFrame = ThemeUtils.resolveBoolean(this, R.attr.gallery_ucrop_show_crop_frame, R.bool.gallery_default_ucrop_show_crop_frame); - mOverlayView.setShowCropFrame(showCropFrame); - boolean showCropGrid = ThemeUtils.resolveBoolean(this, R.attr.gallery_ucrop_show_crop_grid, R.bool.gallery_default_ucrop_show_crop_grid); - mOverlayView.setShowCropGrid(showCropGrid); - int gridRowCount = ThemeUtils.resolveInteger(this, R.attr.gallery_ucrop_grid_column_count, R.integer.gallery_default_ucrop_show_crop_grid_row_count); - mOverlayView.setCropGridRowCount(gridRowCount); - int gridColumnCount = ThemeUtils.resolveInteger(this, R.attr.gallery_ucrop_grid_column_count, R.integer.gallery_default_ucrop_show_crop_grid_column_count); - mOverlayView.setCropGridColumnCount(gridColumnCount); - - // Aspect ratio options宽高比 - float aspectRatioX = mConfiguration.getAspectRatioX(); - float aspectRatioY = mConfiguration.getAspectRatioY(); - - int aspectRationSelectedByDefault = mConfiguration.getSelectedByDefault(); - AspectRatio []aspectRatios = mConfiguration.getAspectRatio(); - - if (aspectRatioX > 0 && aspectRatioY > 0) { - if (mWrapperStateAspectRatio != null) { - mWrapperStateAspectRatio.setVisibility(View.GONE); - } - mGestureCropImageView.setTargetAspectRatio(aspectRatioX / aspectRatioY); - } else if (aspectRatios != null && aspectRationSelectedByDefault < aspectRatios.length) { - float x = aspectRatios[aspectRationSelectedByDefault].getAspectRatioX(); - float y = aspectRatios[aspectRationSelectedByDefault].getAspectRatioY(); - mGestureCropImageView.setTargetAspectRatio(x /y); - } else { - mGestureCropImageView.setTargetAspectRatio(CropImageView.SOURCE_IMAGE_ASPECT_RATIO); - } - - // Result bitmap max size options - int maxSizeX = mConfiguration.getMaxResultWidth(); - int maxSizeY = mConfiguration.getMaxResultHeight(); - if (maxSizeX > 0 && maxSizeY > 0) { - mGestureCropImageView.setMaxResultImageSizeX(maxSizeX); - mGestureCropImageView.setMaxResultImageSizeY(maxSizeY); - } - } - - private void setupViews() { - mShowBottomControls = !mConfiguration.isHideBottomControls(); - if (mShowBottomControls) { - setupAspectRatioWidget(); - setupRotateWidget(); - setupScaleWidget(); - } else { - findViewById(R.id.wrapper_controls).setVisibility(View.GONE); - findViewById(R.id.wrapper_states).setVisibility(View.GONE); - } - } - - private TransformImageView.TransformImageListener mImageListener = new TransformImageView.TransformImageListener() { - @Override - public void onRotate(float currentAngle) { - setAngleText(currentAngle); - } - - @Override - public void onScale(float currentScale) { - setScaleText(currentScale); - } - - @Override - public void onLoadComplete() { - mUCropView.animate().alpha(1).setDuration(300).setInterpolator(new AccelerateInterpolator()); - mBlockingView.setClickable(false); - mShowLoader = false; - supportInvalidateOptionsMenu(); - } - - @Override - public void onLoadFailure(@NonNull Exception e) { - setResultError(e); - } - - }; - - private void setupAspectRatioWidget() { - - int aspectRationSelectedByDefault = mConfiguration.getSelectedByDefault(); - AspectRatio []aspectRatios = mConfiguration.getAspectRatio();//intent.getParcelableArrayListExtra(UCrop.Options.EXTRA_ASPECT_RATIO_OPTIONS); - - if (aspectRatios == null || aspectRatios.length == 0) { - aspectRationSelectedByDefault = 2; - aspectRatios = new AspectRatio[]{new AspectRatio(null, 1, 1), - new AspectRatio(null, 3, 4), - new AspectRatio(getString(R.string.gallery_ucrop_label_original).toUpperCase(), - CropImageView.SOURCE_IMAGE_ASPECT_RATIO, CropImageView.SOURCE_IMAGE_ASPECT_RATIO), - new AspectRatio(null, 3, 2), - new AspectRatio(null, 16, 9) - }; - } - - LinearLayout wrapperAspectRatioList = (LinearLayout) findViewById(R.id.layout_aspect_ratio); - - FrameLayout wrapperAspectRatio; - AspectRatioTextView aspectRatioTextView; - LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT); - lp.weight = 1; - for (AspectRatio aspectRatio : aspectRatios) { - wrapperAspectRatio = (FrameLayout) getLayoutInflater().inflate(R.layout.gallery_ucrop_aspect_ratio, null); - wrapperAspectRatio.setLayoutParams(lp); - aspectRatioTextView = ((AspectRatioTextView) wrapperAspectRatio.getChildAt(0)); - aspectRatioTextView.setActiveColor(mActiveWidgetColor); - aspectRatioTextView.setAspectRatio(aspectRatio); - - wrapperAspectRatioList.addView(wrapperAspectRatio); - mCropAspectRatioViews.add(wrapperAspectRatio); - } - - mCropAspectRatioViews.get(aspectRationSelectedByDefault).setSelected(true); - - for (ViewGroup cropAspectRatioView : mCropAspectRatioViews) { - cropAspectRatioView.setOnClickListener(v -> { - mGestureCropImageView.setTargetAspectRatio( - ((AspectRatioTextView) ((ViewGroup) v).getChildAt(0)).getAspectRatio(v.isSelected())); - mGestureCropImageView.setImageToWrapCropBounds(); - if (!v.isSelected()) { - for (ViewGroup cropAspectRatioView1 : mCropAspectRatioViews) { - cropAspectRatioView1.setSelected(cropAspectRatioView1 == v); - } - } - }); - } - } - - private void setupRotateWidget() { - - ((HorizontalProgressWheelView) findViewById(R.id.rotate_scroll_wheel)) - .setScrollingListener(new HorizontalProgressWheelView.ScrollingListener() { - @Override - public void onScroll(float delta, float totalDistance) { - mGestureCropImageView.postRotate(delta / ROTATE_WIDGET_SENSITIVITY_COEFFICIENT); - } - - @Override - public void onScrollEnd() { - mGestureCropImageView.setImageToWrapCropBounds(); - } - - @Override - public void onScrollStart() { - mGestureCropImageView.cancelAllAnimations(); - } - }); - - ((HorizontalProgressWheelView) findViewById(R.id.rotate_scroll_wheel)).setMiddleLineColor(mActiveWidgetColor); - - - findViewById(R.id.wrapper_reset_rotate).setOnClickListener(v -> resetRotation()); - findViewById(R.id.wrapper_rotate_by_angle).setOnClickListener(v -> rotateByAngle(90)); - } - - private void setupScaleWidget() { - mTextViewScalePercent = ((TextView) findViewById(R.id.text_view_scale)); - ((HorizontalProgressWheelView) findViewById(R.id.scale_scroll_wheel)) - .setScrollingListener(new HorizontalProgressWheelView.ScrollingListener() { - @Override - public void onScroll(float delta, float totalDistance) { - if (delta > 0) { - mGestureCropImageView.zoomInImage(mGestureCropImageView.getCurrentScale() - + delta * ((mGestureCropImageView.getMaxScale() - mGestureCropImageView.getMinScale()) / SCALE_WIDGET_SENSITIVITY_COEFFICIENT)); - } else { - mGestureCropImageView.zoomOutImage(mGestureCropImageView.getCurrentScale() - + delta * ((mGestureCropImageView.getMaxScale() - mGestureCropImageView.getMinScale()) / SCALE_WIDGET_SENSITIVITY_COEFFICIENT)); - } - } - - @Override - public void onScrollEnd() { - mGestureCropImageView.setImageToWrapCropBounds(); - } - - @Override - public void onScrollStart() { - mGestureCropImageView.cancelAllAnimations(); - } - }); - ((HorizontalProgressWheelView) findViewById(R.id.scale_scroll_wheel)).setMiddleLineColor(mActiveWidgetColor); - } - - private void setAngleText(float angle) { - if (mTextViewRotateAngle != null) { - mTextViewRotateAngle.setText(String.format(Locale.getDefault(), "%.1f°", angle)); - } - } - - private void setScaleText(float scale) { - if (mTextViewScalePercent != null) { - mTextViewScalePercent.setText(String.format(Locale.getDefault(), "%d%%", (int) (scale * 100))); - } - } - - private void resetRotation() { - mGestureCropImageView.postRotate(-mGestureCropImageView.getCurrentAngle()); - mGestureCropImageView.setImageToWrapCropBounds(); - } - - private void rotateByAngle(int angle) { - mGestureCropImageView.postRotate(angle); - mGestureCropImageView.setImageToWrapCropBounds(); - } - - private final View.OnClickListener mStateClickListener = v -> { - if (!v.isSelected()) { - setWidgetState(v.getId()); - } - }; - - private void setInitialState() { - if (mShowBottomControls) { - if (mWrapperStateAspectRatio.getVisibility() == View.VISIBLE) { - setWidgetState(R.id.state_aspect_ratio); - } else { - setWidgetState(R.id.state_scale); - } - } else { - mGestureCropImageView.setScaleEnabled(true); - mGestureCropImageView.setRotateEnabled(true); - } - } - - private void setWidgetState(@IdRes int stateViewId) { - if (!mShowBottomControls) return; - - mWrapperStateAspectRatio.setSelected(stateViewId == R.id.state_aspect_ratio); - mWrapperStateRotate.setSelected(stateViewId == R.id.state_rotate); - mWrapperStateScale.setSelected(stateViewId == R.id.state_scale); - - mLayoutAspectRatio.setVisibility(stateViewId == R.id.state_aspect_ratio ? View.VISIBLE : View.GONE); - mLayoutRotate.setVisibility(stateViewId == R.id.state_rotate ? View.VISIBLE : View.GONE); - mLayoutScale.setVisibility(stateViewId == R.id.state_scale ? View.VISIBLE : View.GONE); - - if (stateViewId == R.id.state_scale) { - setAllowedGestures(0); - } else if (stateViewId == R.id.state_rotate) { - setAllowedGestures(1); - } else { - setAllowedGestures(2); - } - } - - private void setAllowedGestures(int tab) { - mGestureCropImageView.setScaleEnabled(mAllowedGestures[tab] == ALL || mAllowedGestures[tab] == SCALE); - mGestureCropImageView.setRotateEnabled(mAllowedGestures[tab] == ALL || mAllowedGestures[tab] == ROTATE); - } - - /** - * Adds view that covers everything below the Toolbar. - * When it's clickable - user won't be able to click/touch anything below the Toolbar. - * Need to block user input while loading and cropping an image. - */ - private void addBlockingView() { - if (mBlockingView == null) { - mBlockingView = new View(this); - RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); - lp.addRule(RelativeLayout.BELOW, R.id.toolbar); - mBlockingView.setLayoutParams(lp); - mBlockingView.setClickable(true); - } - - ((RelativeLayout) findViewById(R.id.ucrop_photobox)).addView(mBlockingView); - } - - protected void cropAndSaveImage() { - mBlockingView.setClickable(true); - mShowLoader = true; - supportInvalidateOptionsMenu(); - - mGestureCropImageView.cropAndSaveImage(mCompressFormat, mCompressQuality, new BitmapCropCallback() { - - @Override - public void onBitmapCropped(@NonNull Uri resultUri) { - setResultUri(resultUri, mGestureCropImageView.getTargetAspectRatio()); - } - - @Override - public void onCropFailure(@NonNull Throwable t) { - setResultError(t); - } - }); - } - - protected void setResultUri(Uri uri, float resultAspectRatio) { - ImageCropBean bean = new ImageCropBean(); - bean.copyMediaBean(mMediaBean); - bean.setCropPath(uri.getPath()); - bean.setAspectRatio(resultAspectRatio); - BaseResultEvent event = new ImageRadioResultEvent(bean); - RxBus.getDefault().post(event); - RxBus.getDefault().post(new CloseRxMediaGridPageEvent()); - finish(); - } - - protected void setResultError(Throwable throwable) { - Logger.e(String.format("Image crop error:%s", throwable.getMessage())); - RxBus.getDefault().post(new CloseRxMediaGridPageEvent()); - finish(); - } - -} diff --git a/library/src/main/java/com/yalantis/ucrop/callback/BitmapCropCallback.java b/library/src/main/java/com/yalantis/ucrop/callback/BitmapCropCallback.java deleted file mode 100755 index b28012c1..00000000 --- a/library/src/main/java/com/yalantis/ucrop/callback/BitmapCropCallback.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.yalantis.ucrop.callback; - -import android.net.Uri; -import android.support.annotation.NonNull; - -public interface BitmapCropCallback { - - void onBitmapCropped(@NonNull Uri resultUri); - - void onCropFailure(@NonNull Throwable t); - -} \ No newline at end of file diff --git a/library/src/main/java/com/yalantis/ucrop/callback/BitmapLoadCallback.java b/library/src/main/java/com/yalantis/ucrop/callback/BitmapLoadCallback.java deleted file mode 100755 index b66d87eb..00000000 --- a/library/src/main/java/com/yalantis/ucrop/callback/BitmapLoadCallback.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.yalantis.ucrop.callback; - -import android.graphics.Bitmap; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.yalantis.ucrop.model.ExifInfo; - -public interface BitmapLoadCallback { - - void onBitmapLoaded(@NonNull Bitmap bitmap, @NonNull ExifInfo exifInfo, @NonNull String imageInputPath, @Nullable String imageOutputPath); - - void onFailure(@NonNull Exception bitmapWorkerException); - -} \ No newline at end of file diff --git a/library/src/main/java/com/yalantis/ucrop/callback/CropBoundsChangeListener.java b/library/src/main/java/com/yalantis/ucrop/callback/CropBoundsChangeListener.java deleted file mode 100755 index 38c1badb..00000000 --- a/library/src/main/java/com/yalantis/ucrop/callback/CropBoundsChangeListener.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.yalantis.ucrop.callback; - -/** - * Interface for crop bound change notifying. - */ -public interface CropBoundsChangeListener { - - void onCropAspectRatioChanged(float cropRatio); - -} \ No newline at end of file diff --git a/library/src/main/java/com/yalantis/ucrop/callback/OverlayViewChangeListener.java b/library/src/main/java/com/yalantis/ucrop/callback/OverlayViewChangeListener.java deleted file mode 100755 index 29218aeb..00000000 --- a/library/src/main/java/com/yalantis/ucrop/callback/OverlayViewChangeListener.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.yalantis.ucrop.callback; - -import android.graphics.RectF; - -/** - * Created by Oleksii Shliama. - */ -public interface OverlayViewChangeListener { - - void onCropRectUpdated(RectF cropRect); - -} \ No newline at end of file diff --git a/library/src/main/java/com/yalantis/ucrop/model/AspectRatio.java b/library/src/main/java/com/yalantis/ucrop/model/AspectRatio.java deleted file mode 100755 index 65ca4548..00000000 --- a/library/src/main/java/com/yalantis/ucrop/model/AspectRatio.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.yalantis.ucrop.model; - -import android.os.Parcel; -import android.os.Parcelable; -import android.support.annotation.Nullable; - -/** - * Created by Oleksii Shliama [https://github.com/shliama] on 6/24/16. - */ -public class AspectRatio implements Parcelable { - - @Nullable - private final String mAspectRatioTitle; - private final float mAspectRatioX; - private final float mAspectRatioY; - - public AspectRatio(@Nullable String aspectRatioTitle, float aspectRatioX, float aspectRatioY) { - mAspectRatioTitle = aspectRatioTitle; - mAspectRatioX = aspectRatioX; - mAspectRatioY = aspectRatioY; - } - - protected AspectRatio(Parcel in) { - mAspectRatioTitle = in.readString(); - mAspectRatioX = in.readFloat(); - mAspectRatioY = in.readFloat(); - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeString(mAspectRatioTitle); - dest.writeFloat(mAspectRatioX); - dest.writeFloat(mAspectRatioY); - } - - @Override - public int describeContents() { - return 0; - } - - public static final Creator CREATOR = new Creator() { - @Override - public AspectRatio createFromParcel(Parcel in) { - return new AspectRatio(in); - } - - @Override - public AspectRatio[] newArray(int size) { - return new AspectRatio[size]; - } - }; - - @Nullable - public String getAspectRatioTitle() { - return mAspectRatioTitle; - } - - public float getAspectRatioX() { - return mAspectRatioX; - } - - public float getAspectRatioY() { - return mAspectRatioY; - } - -} diff --git a/library/src/main/java/com/yalantis/ucrop/model/CropParameters.java b/library/src/main/java/com/yalantis/ucrop/model/CropParameters.java deleted file mode 100755 index 17d8a7e7..00000000 --- a/library/src/main/java/com/yalantis/ucrop/model/CropParameters.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.yalantis.ucrop.model; - -import android.graphics.Bitmap; - -/** - * Created by Oleksii Shliama [https://github.com/shliama] on 6/21/16. - */ -public class CropParameters { - - private int mMaxResultImageSizeX, mMaxResultImageSizeY; - - private Bitmap.CompressFormat mCompressFormat; - private int mCompressQuality; - private String mImageInputPath, mImageOutputPath; - private ExifInfo mExifInfo; - - - public CropParameters(int maxResultImageSizeX, int maxResultImageSizeY, - Bitmap.CompressFormat compressFormat, int compressQuality, - String imageInputPath, String imageOutputPath, ExifInfo exifInfo) { - mMaxResultImageSizeX = maxResultImageSizeX; - mMaxResultImageSizeY = maxResultImageSizeY; - mCompressFormat = compressFormat; - mCompressQuality = compressQuality; - mImageInputPath = imageInputPath; - mImageOutputPath = imageOutputPath; - mExifInfo = exifInfo; - } - - public int getMaxResultImageSizeX() { - return mMaxResultImageSizeX; - } - - public int getMaxResultImageSizeY() { - return mMaxResultImageSizeY; - } - - public Bitmap.CompressFormat getCompressFormat() { - return mCompressFormat; - } - - public int getCompressQuality() { - return mCompressQuality; - } - - public String getImageInputPath() { - return mImageInputPath; - } - - public String getImageOutputPath() { - return mImageOutputPath; - } - - public ExifInfo getExifInfo() { - return mExifInfo; - } - -} diff --git a/library/src/main/java/com/yalantis/ucrop/model/ExifInfo.java b/library/src/main/java/com/yalantis/ucrop/model/ExifInfo.java deleted file mode 100755 index 96da038a..00000000 --- a/library/src/main/java/com/yalantis/ucrop/model/ExifInfo.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.yalantis.ucrop.model; - -/** - * Created by Oleksii Shliama [https://github.com/shliama] on 6/21/16. - */ -public class ExifInfo { - - private int mExifOrientation; - private int mExifDegrees; - private int mExifTranslation; - - public ExifInfo(int exifOrientation, int exifDegrees, int exifTranslation) { - mExifOrientation = exifOrientation; - mExifDegrees = exifDegrees; - mExifTranslation = exifTranslation; - } - - public int getExifOrientation() { - return mExifOrientation; - } - - public int getExifDegrees() { - return mExifDegrees; - } - - public int getExifTranslation() { - return mExifTranslation; - } - - public void setExifOrientation(int exifOrientation) { - mExifOrientation = exifOrientation; - } - - public void setExifDegrees(int exifDegrees) { - mExifDegrees = exifDegrees; - } - - public void setExifTranslation(int exifTranslation) { - mExifTranslation = exifTranslation; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - ExifInfo exifInfo = (ExifInfo) o; - - if (mExifOrientation != exifInfo.mExifOrientation) return false; - if (mExifDegrees != exifInfo.mExifDegrees) return false; - return mExifTranslation == exifInfo.mExifTranslation; - - } - - @Override - public int hashCode() { - int result = mExifOrientation; - result = 31 * result + mExifDegrees; - result = 31 * result + mExifTranslation; - return result; - } - -} diff --git a/library/src/main/java/com/yalantis/ucrop/model/ImageState.java b/library/src/main/java/com/yalantis/ucrop/model/ImageState.java deleted file mode 100755 index ebaab9c1..00000000 --- a/library/src/main/java/com/yalantis/ucrop/model/ImageState.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.yalantis.ucrop.model; - -import android.graphics.RectF; - -/** - * Created by Oleksii Shliama [https://github.com/shliama] on 6/21/16. - */ -public class ImageState { - - private RectF mCropRect; - private RectF mCurrentImageRect; - - private float mCurrentScale, mCurrentAngle; - - public ImageState(RectF cropRect, RectF currentImageRect, float currentScale, float currentAngle) { - mCropRect = cropRect; - mCurrentImageRect = currentImageRect; - mCurrentScale = currentScale; - mCurrentAngle = currentAngle; - } - - public RectF getCropRect() { - return mCropRect; - } - - public RectF getCurrentImageRect() { - return mCurrentImageRect; - } - - public float getCurrentScale() { - return mCurrentScale; - } - - public float getCurrentAngle() { - return mCurrentAngle; - } -} diff --git a/library/src/main/java/com/yalantis/ucrop/task/BitmapCropTask.java b/library/src/main/java/com/yalantis/ucrop/task/BitmapCropTask.java deleted file mode 100755 index 452368fc..00000000 --- a/library/src/main/java/com/yalantis/ucrop/task/BitmapCropTask.java +++ /dev/null @@ -1,190 +0,0 @@ -package com.yalantis.ucrop.task; - -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.RectF; -import android.media.ExifInterface; -import android.net.Uri; -import android.os.AsyncTask; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.util.Log; - -import com.yalantis.ucrop.callback.BitmapCropCallback; -import com.yalantis.ucrop.model.CropParameters; -import com.yalantis.ucrop.model.ExifInfo; -import com.yalantis.ucrop.model.ImageState; -import com.yalantis.ucrop.util.FileUtils; -import com.yalantis.ucrop.util.ImageHeaderParser; - -import java.io.File; -import java.io.IOException; - -/** - * Crops part of image that fills the crop bounds. - *

- * First image is downscaled if max size was set and if resulting image is larger that max size. - * Then image is rotated accordingly. - * Finally new Bitmap object is created and saved to file. - */ -public class BitmapCropTask extends AsyncTask { - - private static final String TAG = "BitmapCropTask"; - - static { - System.loadLibrary("ucrop"); - } - - private Bitmap mViewBitmap; - - private final RectF mCropRect; - private final RectF mCurrentImageRect; - - private float mCurrentScale, mCurrentAngle; - private final int mMaxResultImageSizeX, mMaxResultImageSizeY; - - private final Bitmap.CompressFormat mCompressFormat; - private final int mCompressQuality; - private final String mImageInputPath, mImageOutputPath; - private final ExifInfo mExifInfo; - private final BitmapCropCallback mCropCallback; - - public BitmapCropTask(@Nullable Bitmap viewBitmap, @NonNull ImageState imageState, @NonNull CropParameters cropParameters, - @Nullable BitmapCropCallback cropCallback) { - - mViewBitmap = viewBitmap; - mCropRect = imageState.getCropRect(); - mCurrentImageRect = imageState.getCurrentImageRect(); - - mCurrentScale = imageState.getCurrentScale(); - mCurrentAngle = imageState.getCurrentAngle(); - mMaxResultImageSizeX = cropParameters.getMaxResultImageSizeX(); - mMaxResultImageSizeY = cropParameters.getMaxResultImageSizeY(); - - mCompressFormat = cropParameters.getCompressFormat(); - mCompressQuality = cropParameters.getCompressQuality(); - - mImageInputPath = cropParameters.getImageInputPath(); - mImageOutputPath = cropParameters.getImageOutputPath(); - mExifInfo = cropParameters.getExifInfo(); - - mCropCallback = cropCallback; - } - - @Override - @Nullable - protected Throwable doInBackground(Void... params) { - if (mViewBitmap == null) { - return new NullPointerException("ViewBitmap is null"); - } else if (mViewBitmap.isRecycled()) { - return new NullPointerException("ViewBitmap is recycled"); - } else if (mCurrentImageRect.isEmpty()) { - return new NullPointerException("CurrentImageRect is empty"); - } - - float resizeScale = resize(); - - try { - crop(resizeScale); - mViewBitmap = null; - } catch (Throwable throwable) { - return throwable; - } - - return null; - } - - private float resize() { - final BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - BitmapFactory.decodeFile(mImageInputPath, options); - - boolean swapSides = mExifInfo.getExifDegrees() == 90 || mExifInfo.getExifDegrees() == 270; - float scaleX = (swapSides ? options.outHeight : options.outWidth) / (float) mViewBitmap.getWidth(); - float scaleY = (swapSides ? options.outWidth : options.outHeight) / (float) mViewBitmap.getHeight(); - - float resizeScale = Math.min(scaleX, scaleY); - - mCurrentScale /= resizeScale; - - resizeScale = 1; - if (mMaxResultImageSizeX > 0 && mMaxResultImageSizeY > 0) { - float cropWidth = mCropRect.width() / mCurrentScale; - float cropHeight = mCropRect.height() / mCurrentScale; - - if (cropWidth > mMaxResultImageSizeX || cropHeight > mMaxResultImageSizeY) { - - scaleX = mMaxResultImageSizeX / cropWidth; - scaleY = mMaxResultImageSizeY / cropHeight; - resizeScale = Math.min(scaleX, scaleY); - - mCurrentScale /= resizeScale; - } - } - return resizeScale; - } - - private boolean crop(float resizeScale) throws IOException { - ExifInterface originalExif = new ExifInterface(mImageInputPath); - - int top = Math.round((mCropRect.top - mCurrentImageRect.top) / mCurrentScale); - int left = Math.round((mCropRect.left - mCurrentImageRect.left) / mCurrentScale); - int width = Math.round(mCropRect.width() / mCurrentScale); - int height = Math.round(mCropRect.height() / mCurrentScale); - - boolean shouldCrop = shouldCrop(width, height); - Log.i(TAG, "Should crop: " + shouldCrop); - - if (shouldCrop) { - boolean cropped = cropCImg(mImageInputPath, mImageOutputPath, - left, top, width, height, mCurrentAngle, resizeScale, - mCompressFormat.ordinal(), mCompressQuality, - mExifInfo.getExifDegrees(), mExifInfo.getExifTranslation()); - if (cropped) { - ImageHeaderParser.copyExif(originalExif, width, height, mImageOutputPath); - } - return cropped; - } else { - FileUtils.copyFile(mImageInputPath, mImageOutputPath); - return false; - } - } - - /** - * Check whether an image should be cropped at all or just file can be copied to the destination path. - * For each 1000 pixels there is one pixel of error due to matrix calculations etc. - * - * @param width - crop area width - * @param height - crop area height - * @return - true if image must be cropped, false - if original image fits requirements - */ - private boolean shouldCrop(int width, int height) { - int pixelError = 1; - pixelError += Math.round(Math.max(width, height) / 1000f); - return (mMaxResultImageSizeX > 0 && mMaxResultImageSizeY > 0) - || Math.abs(mCropRect.left - mCurrentImageRect.left) > pixelError - || Math.abs(mCropRect.top - mCurrentImageRect.top) > pixelError - || Math.abs(mCropRect.bottom - mCurrentImageRect.bottom) > pixelError - || Math.abs(mCropRect.right - mCurrentImageRect.right) > pixelError; - } - - @SuppressWarnings("JniMissingFunction") - native public boolean - cropCImg(String inputPath, String outputPath, - int left, int top, int width, int height, - float angle, float resizeScale, - int format, int quality, - int exifDegrees, int exifTranslation) throws IOException, OutOfMemoryError; - - @Override - protected void onPostExecute(@Nullable Throwable t) { - if (mCropCallback != null) { - if (t == null) { - mCropCallback.onBitmapCropped(Uri.fromFile(new File(mImageOutputPath))); - } else { - mCropCallback.onCropFailure(t); - } - } - } - -} diff --git a/library/src/main/java/com/yalantis/ucrop/task/BitmapLoadTask.java b/library/src/main/java/com/yalantis/ucrop/task/BitmapLoadTask.java deleted file mode 100755 index 22587c43..00000000 --- a/library/src/main/java/com/yalantis/ucrop/task/BitmapLoadTask.java +++ /dev/null @@ -1,214 +0,0 @@ -package com.yalantis.ucrop.task; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Matrix; -import android.net.Uri; -import android.os.AsyncTask; -import android.os.Build; -import android.os.ParcelFileDescriptor; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.text.TextUtils; -import android.util.Log; - -import com.yalantis.ucrop.callback.BitmapLoadCallback; -import com.yalantis.ucrop.model.ExifInfo; -import com.yalantis.ucrop.util.BitmapLoadUtils; -import com.yalantis.ucrop.util.FileUtils; - -import java.io.File; -import java.io.FileDescriptor; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -/** - * Creates and returns a Bitmap for a given Uri(String url). - * inSampleSize is calculated based on requiredWidth property. However can be adjusted if OOM occurs. - * If any EXIF config is found - bitmap is transformed properly. - */ -public class BitmapLoadTask extends AsyncTask { - - private static final String TAG = "BitmapWorkerTask"; - - private final Context mContext; - private Uri mInputUri; - private Uri mOutputUri; - private final int mRequiredWidth; - private final int mRequiredHeight; - - private final BitmapLoadCallback mBitmapLoadCallback; - - public static class BitmapWorkerResult { - - Bitmap mBitmapResult; - ExifInfo mExifInfo; - Exception mBitmapWorkerException; - - public BitmapWorkerResult(@NonNull Bitmap bitmapResult, @NonNull ExifInfo exifInfo) { - mBitmapResult = bitmapResult; - mExifInfo = exifInfo; - } - - public BitmapWorkerResult(@NonNull Exception bitmapWorkerException) { - mBitmapWorkerException = bitmapWorkerException; - } - - } - - public BitmapLoadTask(@NonNull Context context, - @NonNull Uri inputUri, @Nullable Uri outputUri, - int requiredWidth, int requiredHeight, - BitmapLoadCallback loadCallback) { - mContext = context; - mInputUri = inputUri; - mOutputUri = outputUri; - mRequiredWidth = requiredWidth; - mRequiredHeight = requiredHeight; - mBitmapLoadCallback = loadCallback; - } - - @Override - @NonNull - protected BitmapWorkerResult doInBackground(Void... params) { - if (mInputUri == null) { - return new BitmapWorkerResult(new NullPointerException("Input Uri cannot be null")); - } - - try { - processInputUri(); - } catch (NullPointerException | IOException e) { - return new BitmapWorkerResult(e); - } - - final ParcelFileDescriptor parcelFileDescriptor; - try { - parcelFileDescriptor = mContext.getContentResolver().openFileDescriptor(mInputUri, "r"); - } catch (FileNotFoundException e) { - return new BitmapWorkerResult(e); - } - - final FileDescriptor fileDescriptor; - if (parcelFileDescriptor != null) { - fileDescriptor = parcelFileDescriptor.getFileDescriptor(); - } else { - return new BitmapWorkerResult(new NullPointerException("ParcelFileDescriptor was null for given Uri: [" + mInputUri + "]")); - } - - final BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - BitmapFactory.decodeFileDescriptor(fileDescriptor, null, options); - if (options.outWidth == -1 || options.outHeight == -1) { - return new BitmapWorkerResult(new IllegalArgumentException("Bounds for bitmap could not be retrieved from the Uri: [" + mInputUri + "]")); - } - - options.inSampleSize = BitmapLoadUtils.calculateInSampleSize(options, mRequiredWidth, mRequiredHeight); - options.inJustDecodeBounds = false; - - Bitmap decodeSampledBitmap = null; - - boolean decodeAttemptSuccess = false; - while (!decodeAttemptSuccess) { - try { - decodeSampledBitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor, null, options); - decodeAttemptSuccess = true; - } catch (OutOfMemoryError error) { - Log.e(TAG, "doInBackground: BitmapFactory.decodeFileDescriptor: ", error); - options.inSampleSize *= 2; - } - } - - if (decodeSampledBitmap == null) { - return new BitmapWorkerResult(new IllegalArgumentException("Bitmap could not be decoded from the Uri: [" + mInputUri + "]")); - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - BitmapLoadUtils.close(parcelFileDescriptor); - } - - int exifOrientation = BitmapLoadUtils.getExifOrientation(mContext, mInputUri); - int exifDegrees = BitmapLoadUtils.exifToDegrees(exifOrientation); - int exifTranslation = BitmapLoadUtils.exifToTranslation(exifOrientation); - - ExifInfo exifInfo = new ExifInfo(exifOrientation, exifDegrees, exifTranslation); - - Matrix matrix = new Matrix(); - if (exifDegrees != 0) { - matrix.preRotate(exifDegrees); - } - if (exifTranslation != 1) { - matrix.postScale(exifTranslation, 1); - } - if (!matrix.isIdentity()) { - return new BitmapWorkerResult(BitmapLoadUtils.transformBitmap(decodeSampledBitmap, matrix), exifInfo); - } - - return new BitmapWorkerResult(decodeSampledBitmap, exifInfo); - } - - private void processInputUri() throws NullPointerException, IOException { - String inputUriScheme = mInputUri.getScheme(); - Log.d(TAG, "Uri scheme: " + inputUriScheme); - if ("content".equals(inputUriScheme)) { - String path = FileUtils.getPath(mContext, mInputUri); - if (!TextUtils.isEmpty(path) && new File(path).exists()) { - mInputUri = Uri.fromFile(new File(path)); - } else { - try { - copyFile(mInputUri, mOutputUri); - } catch (NullPointerException | IOException e) { - Log.e(TAG, "Copying failed", e); - throw e; - } - } - } else if (!"file".equals(inputUriScheme)) { - Log.e(TAG, "Invalid Uri scheme " + inputUriScheme); - throw new IllegalArgumentException("Invalid Uri scheme" + inputUriScheme); - } - } - - private void copyFile(@NonNull Uri inputUri, @Nullable Uri outputUri) throws NullPointerException, IOException { - Log.d(TAG, "copyFile"); - - if (outputUri == null) { - throw new NullPointerException("Output Uri is null - cannot copy image"); - } - - InputStream inputStream = null; - OutputStream outputStream = null; - try { - inputStream = mContext.getContentResolver().openInputStream(inputUri); - outputStream = new FileOutputStream(new File(outputUri.getPath())); - if (inputStream == null) { - throw new NullPointerException("InputStream for given input Uri is null"); - } - - byte buffer[] = new byte[1024]; - int length; - while ((length = inputStream.read(buffer)) > 0) { - outputStream.write(buffer, 0, length); - } - } finally { - BitmapLoadUtils.close(outputStream); - BitmapLoadUtils.close(inputStream); - - // swap uris, because input image was copied to the output destination - // (cropped image will override it later) - mInputUri = mOutputUri; - } - } - - @Override - protected void onPostExecute(@NonNull BitmapWorkerResult result) { - if (result.mBitmapWorkerException == null) { - mBitmapLoadCallback.onBitmapLoaded(result.mBitmapResult, result.mExifInfo, mInputUri.getPath(), (mOutputUri == null) ? null : mOutputUri.getPath()); - } else { - mBitmapLoadCallback.onFailure(result.mBitmapWorkerException); - } - } - -} \ No newline at end of file diff --git a/library/src/main/java/com/yalantis/ucrop/util/BitmapLoadUtils.java b/library/src/main/java/com/yalantis/ucrop/util/BitmapLoadUtils.java deleted file mode 100755 index 97b43078..00000000 --- a/library/src/main/java/com/yalantis/ucrop/util/BitmapLoadUtils.java +++ /dev/null @@ -1,159 +0,0 @@ -package com.yalantis.ucrop.util; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.Matrix; -import android.graphics.Point; -import android.media.ExifInterface; -import android.net.Uri; -import android.os.Build; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.util.Log; -import android.view.Display; -import android.view.WindowManager; - -import com.yalantis.ucrop.callback.BitmapLoadCallback; -import com.yalantis.ucrop.task.BitmapLoadTask; - -import java.io.Closeable; -import java.io.IOException; -import java.io.InputStream; - -/** - * Created by Oleksii Shliama (https://github.com/shliama). - */ -public class BitmapLoadUtils { - - private static final String TAG = "BitmapLoadUtils"; - - public static void decodeBitmapInBackground(@NonNull Context context, - @NonNull Uri uri, @Nullable Uri outputUri, - int requiredWidth, int requiredHeight, - BitmapLoadCallback loadCallback) { - - new BitmapLoadTask(context, uri, outputUri, requiredWidth, requiredHeight, loadCallback).execute(); - } - - public static Bitmap transformBitmap(@NonNull Bitmap bitmap, @NonNull Matrix transformMatrix) { - try { - Bitmap converted = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), transformMatrix, true); - if (!bitmap.sameAs(converted)) { - bitmap = converted; - } - } catch (OutOfMemoryError error) { - Log.e(TAG, "transformBitmap: ", error); - } - return bitmap; - } - - public static int calculateInSampleSize(@NonNull BitmapFactory.Options options, int reqWidth, int reqHeight) { - // Raw height and width of image - final int height = options.outHeight; - final int width = options.outWidth; - int inSampleSize = 1; - - if (height > reqHeight || width > reqWidth) { - // Calculate the largest inSampleSize value that is a power of 2 and keeps both - // height and width lower or equal to the requested height and width. - while ((height / inSampleSize) > reqHeight || (width / inSampleSize) > reqWidth) { - inSampleSize *= 2; - } - } - return inSampleSize; - } - - public static int getExifOrientation(@NonNull Context context, @NonNull Uri imageUri) { - int orientation = ExifInterface.ORIENTATION_UNDEFINED; - try { - InputStream stream = context.getContentResolver().openInputStream(imageUri); - if (stream == null) { - return orientation; - } - orientation = new ImageHeaderParser(stream).getOrientation(); - close(stream); - } catch (IOException e) { - Log.e(TAG, "getExifOrientation: " + imageUri.toString(), e); - } - return orientation; - } - - public static int exifToDegrees(int exifOrientation) { - int rotation; - switch (exifOrientation) { - case ExifInterface.ORIENTATION_ROTATE_90: - case ExifInterface.ORIENTATION_TRANSPOSE: - rotation = 90; - break; - case ExifInterface.ORIENTATION_ROTATE_180: - case ExifInterface.ORIENTATION_FLIP_VERTICAL: - rotation = 180; - break; - case ExifInterface.ORIENTATION_ROTATE_270: - case ExifInterface.ORIENTATION_TRANSVERSE: - rotation = 270; - break; - default: - rotation = 0; - } - return rotation; - } - - public static int exifToTranslation(int exifOrientation) { - int translation; - switch (exifOrientation) { - case ExifInterface.ORIENTATION_FLIP_HORIZONTAL: - case ExifInterface.ORIENTATION_FLIP_VERTICAL: - case ExifInterface.ORIENTATION_TRANSPOSE: - case ExifInterface.ORIENTATION_TRANSVERSE: - translation = -1; - break; - default: - translation = 1; - } - return translation; - } - - /** - * This method calculates maximum size of both width and height of bitmap. - * It is twice the device screen diagonal for default implementation (extra quality to zoom image). - * Size cannot exceed max texture size. - * - * @return - max bitmap size in pixels. - */ - @SuppressWarnings({"SuspiciousNameCombination", "deprecation"}) - public static int calculateMaxBitmapSize(@NonNull Context context) { - WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); - Display display = wm.getDefaultDisplay(); - - Point size = new Point(); - int width, height; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { - display.getSize(size); - width = size.x; - height = size.y; - } else { - width = display.getWidth(); - height = display.getHeight(); - } - - int screenDiagonal = (int) Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)); - - Canvas canvas = new Canvas(); - return Math.min(screenDiagonal * 2, Math.min(canvas.getMaximumBitmapWidth(), canvas.getMaximumBitmapHeight())); - } - - @SuppressWarnings("ConstantConditions") - public static void close(@Nullable Closeable c) { - if (c != null && c instanceof Closeable) { // java.lang.IncompatibleClassChangeError: interface not implemented - try { - c.close(); - } catch (IOException e) { - // silence - } - } - } - -} \ No newline at end of file diff --git a/library/src/main/java/com/yalantis/ucrop/util/CubicEasing.java b/library/src/main/java/com/yalantis/ucrop/util/CubicEasing.java deleted file mode 100755 index 3c81b8ec..00000000 --- a/library/src/main/java/com/yalantis/ucrop/util/CubicEasing.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.yalantis.ucrop.util; - -public final class CubicEasing { - - public static float easeOut(float time, float start, float end, float duration) { - return end * ((time = time / duration - 1.0f) * time * time + 1.0f) + start; - } - - public static float easeIn(float time, float start, float end, float duration) { - return end * (time /= duration) * time * time + start; - } - - public static float easeInOut(float time, float start, float end, float duration) { - return (time /= duration / 2.0f) < 1.0f ? end / 2.0f * time * time * time + start : end / 2.0f * ((time -= 2.0f) * time * time + 2.0f) + start; - } - -} diff --git a/library/src/main/java/com/yalantis/ucrop/util/FastBitmapDrawable.java b/library/src/main/java/com/yalantis/ucrop/util/FastBitmapDrawable.java deleted file mode 100755 index 53c621bb..00000000 --- a/library/src/main/java/com/yalantis/ucrop/util/FastBitmapDrawable.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.yalantis.ucrop.util; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.ColorFilter; -import android.graphics.Paint; -import android.graphics.PixelFormat; -import android.graphics.drawable.Drawable; - -public class FastBitmapDrawable extends Drawable { - - private final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG); - - private Bitmap mBitmap; - private int mAlpha; - private int mWidth, mHeight; - - public FastBitmapDrawable(Bitmap b) { - mAlpha = 255; - setBitmap(b); - } - - @Override - public void draw(Canvas canvas) { - if (mBitmap != null && !mBitmap.isRecycled()) { - canvas.drawBitmap(mBitmap, null, getBounds(), mPaint); - } - } - - @Override - public void setColorFilter(ColorFilter cf) { - mPaint.setColorFilter(cf); - } - - @Override - public int getOpacity() { - return PixelFormat.TRANSLUCENT; - } - - public void setFilterBitmap(boolean filterBitmap) { - mPaint.setFilterBitmap(filterBitmap); - } - - public int getAlpha() { - return mAlpha; - } - - @Override - public void setAlpha(int alpha) { - mAlpha = alpha; - mPaint.setAlpha(alpha); - } - - @Override - public int getIntrinsicWidth() { - return mWidth; - } - - @Override - public int getIntrinsicHeight() { - return mHeight; - } - - @Override - public int getMinimumWidth() { - return mWidth; - } - - @Override - public int getMinimumHeight() { - return mHeight; - } - - public Bitmap getBitmap() { - return mBitmap; - } - - public void setBitmap(Bitmap b) { - mBitmap = b; - if (b != null) { - mWidth = mBitmap.getWidth(); - mHeight = mBitmap.getHeight(); - } else { - mWidth = mHeight = 0; - } - } - -} diff --git a/library/src/main/java/com/yalantis/ucrop/util/FileUtils.java b/library/src/main/java/com/yalantis/ucrop/util/FileUtils.java deleted file mode 100755 index 5481ce6e..00000000 --- a/library/src/main/java/com/yalantis/ucrop/util/FileUtils.java +++ /dev/null @@ -1,537 +0,0 @@ -/* - * Copyright (C) 2007-2008 OpenIntents.org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.yalantis.ucrop.util; - -import android.annotation.SuppressLint; -import android.content.ContentResolver; -import android.content.ContentUris; -import android.content.Context; -import android.content.Intent; -import android.database.Cursor; -import android.database.DatabaseUtils; -import android.graphics.Bitmap; -import android.net.Uri; -import android.os.Build; -import android.os.Environment; -import android.provider.DocumentsContract; -import android.provider.MediaStore; -import android.support.annotation.NonNull; -import android.util.Log; -import android.webkit.MimeTypeMap; - -import java.io.File; -import java.io.FileFilter; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.channels.FileChannel; -import java.text.DecimalFormat; -import java.util.Comparator; - -/** - * @author Peli - * @author paulburke (ipaulpro) - * @version 2013-12-11 - */ -public class FileUtils { - private FileUtils() { - } //private constructor to enforce Singleton pattern - - /** - * TAG for log messages. - */ - static final String TAG = "FileUtils"; - private static final boolean DEBUG = false; // Set to true to enable logging - - public static final String MIME_TYPE_AUDIO = "audio/*"; - public static final String MIME_TYPE_TEXT = "text/*"; - public static final String MIME_TYPE_IMAGE = "image/*"; - public static final String MIME_TYPE_VIDEO = "video/*"; - public static final String MIME_TYPE_APP = "application/*"; - - public static final String HIDDEN_PREFIX = "."; - - /** - * Gets the extension of a file name, like ".png" or ".jpg". - * - * @param uri - * @return Extension including the dot("."); "" if there is no extension; - * null if uri was null. - */ - public static String getExtension(String uri) { - if (uri == null) { - return null; - } - - int dot = uri.lastIndexOf("."); - if (dot >= 0) { - return uri.substring(dot); - } else { - // No extension. - return ""; - } - } - - /** - * @return Whether the URI is a local one. - */ - public static boolean isLocal(String url) { - if (url != null && !url.startsWith("http://") && !url.startsWith("https://")) { - return true; - } - return false; - } - - /** - * @return True if Uri is a MediaStore Uri. - * @author paulburke - */ - public static boolean isMediaUri(Uri uri) { - return "media".equalsIgnoreCase(uri.getAuthority()); - } - - /** - * Convert File into Uri. - * - * @param file - * @return uri - */ - public static Uri getUri(File file) { - if (file != null) { - return Uri.fromFile(file); - } - return null; - } - - /** - * Returns the path only (without file name). - * - * @param file - * @return - */ - public static File getPathWithoutFilename(File file) { - if (file != null) { - if (file.isDirectory()) { - // no file to be split off. Return everything - return file; - } else { - String filename = file.getName(); - String filepath = file.getAbsolutePath(); - - // Construct path without file name. - String pathwithoutname = filepath.substring(0, - filepath.length() - filename.length()); - if (pathwithoutname.endsWith("/")) { - pathwithoutname = pathwithoutname.substring(0, pathwithoutname.length() - 1); - } - return new File(pathwithoutname); - } - } - return null; - } - - /** - * @return The MIME type for the given file. - */ - public static String getMimeType(File file) { - - String extension = getExtension(file.getName()); - - if (extension.length() > 0) - return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.substring(1)); - - return "application/octet-stream"; - } - - /** - * @return The MIME type for the give Uri. - */ - public static String getMimeType(Context context, Uri uri) { - File file = new File(getPath(context, uri)); - return getMimeType(file); - } - - /** - * @param uri The Uri to check. - * @return Whether the Uri authority is ExternalStorageProvider. - * @author paulburke - */ - public static boolean isExternalStorageDocument(Uri uri) { - return "com.android.externalstorage.documents".equals(uri.getAuthority()); - } - - /** - * @param uri The Uri to check. - * @return Whether the Uri authority is DownloadsProvider. - * @author paulburke - */ - public static boolean isDownloadsDocument(Uri uri) { - return "com.android.providers.downloads.documents".equals(uri.getAuthority()); - } - - /** - * @param uri The Uri to check. - * @return Whether the Uri authority is MediaProvider. - * @author paulburke - */ - public static boolean isMediaDocument(Uri uri) { - return "com.android.providers.media.documents".equals(uri.getAuthority()); - } - - /** - * @param uri The Uri to check. - * @return Whether the Uri authority is Google Photos. - */ - public static boolean isGooglePhotosUri(Uri uri) { - return "com.google.android.apps.photos.content".equals(uri.getAuthority()); - } - - /** - * Get the value of the data column for this Uri. This is useful for - * MediaStore Uris, and other file-based ContentProviders. - * - * @param context The context. - * @param uri The Uri to query. - * @param selection (Optional) Filter used in the query. - * @param selectionArgs (Optional) Selection arguments used in the query. - * @return The value of the _data column, which is typically a file path. - * @author paulburke - */ - public static String getDataColumn(Context context, Uri uri, String selection, - String[] selectionArgs) { - - Cursor cursor = null; - final String column = "_data"; - final String[] projection = { - column - }; - - try { - cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, - null); - if (cursor != null && cursor.moveToFirst()) { - if (DEBUG) - DatabaseUtils.dumpCursor(cursor); - - final int column_index = cursor.getColumnIndexOrThrow(column); - return cursor.getString(column_index); - } - } catch (IllegalArgumentException ex) { - Log.i(TAG, "getDataColumn: _data", ex); - } finally { - if (cursor != null) - cursor.close(); - } - return null; - } - - /** - * Get a file path from a Uri. This will get the the path for Storage Access - * Framework Documents, as well as the _data field for the MediaStore and - * other file-based ContentProviders.
- *
- * Callers should check whether the path is local before assuming it - * represents a local file. - * - * @param context The context. - * @param uri The Uri to query. - * @author paulburke - * @see #isLocal(String) - * @see #getFile(Context, Uri) - */ - @SuppressLint("NewApi") - public static String getPath(final Context context, final Uri uri) { - - if (DEBUG) - Log.d(TAG + " File -", - "Authority: " + uri.getAuthority() + - ", Fragment: " + uri.getFragment() + - ", Port: " + uri.getPort() + - ", Query: " + uri.getQuery() + - ", Scheme: " + uri.getScheme() + - ", Host: " + uri.getHost() + - ", Segments: " + uri.getPathSegments().toString() - ); - - final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; - - // DocumentProvider - if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { - if (isExternalStorageDocument(uri)) { - final String docId = DocumentsContract.getDocumentId(uri); - final String[] split = docId.split(":"); - final String type = split[0]; - - if ("primary".equalsIgnoreCase(type)) { - return Environment.getExternalStorageDirectory() + "/" + split[1]; - } - - // TODO handle non-primary volumes - } - // DownloadsProvider - else if (isDownloadsDocument(uri)) { - - final String id = DocumentsContract.getDocumentId(uri); - final Uri contentUri = ContentUris.withAppendedId( - Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); - - return getDataColumn(context, contentUri, null, null); - } - // MediaProvider - else if (isMediaDocument(uri)) { - final String docId = DocumentsContract.getDocumentId(uri); - final String[] split = docId.split(":"); - final String type = split[0]; - - Uri contentUri = null; - if ("image".equals(type)) { - contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; - } else if ("video".equals(type)) { - contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; - } else if ("audio".equals(type)) { - contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; - } - - final String selection = "_id=?"; - final String[] selectionArgs = new String[]{ - split[1] - }; - - return getDataColumn(context, contentUri, selection, selectionArgs); - } - } - // MediaStore (and general) - else if ("content".equalsIgnoreCase(uri.getScheme())) { - - // Return the remote address - if (isGooglePhotosUri(uri)) - return uri.getLastPathSegment(); - - return getDataColumn(context, uri, null, null); - } - // File - else if ("file".equalsIgnoreCase(uri.getScheme())) { - return uri.getPath(); - } - - return null; - } - - /** - * Convert Uri into File, if possible. - * - * @return file A local file that the Uri was pointing to, or null if the - * Uri is unsupported or pointed to a remote resource. - * @author paulburke - * @see #getPath(Context, Uri) - */ - public static File getFile(Context context, Uri uri) { - if (uri != null) { - String path = getPath(context, uri); - if (path != null && isLocal(path)) { - return new File(path); - } - } - return null; - } - - /** - * Get the file size in a human-readable string. - * - * @param size - * @return - * @author paulburke - */ - public static String getReadableFileSize(int size) { - final int BYTES_IN_KILOBYTES = 1024; - final DecimalFormat dec = new DecimalFormat("###.#"); - final String KILOBYTES = " KB"; - final String MEGABYTES = " MB"; - final String GIGABYTES = " GB"; - float fileSize = 0; - String suffix = KILOBYTES; - - if (size > BYTES_IN_KILOBYTES) { - fileSize = size / BYTES_IN_KILOBYTES; - if (fileSize > BYTES_IN_KILOBYTES) { - fileSize = fileSize / BYTES_IN_KILOBYTES; - if (fileSize > BYTES_IN_KILOBYTES) { - fileSize = fileSize / BYTES_IN_KILOBYTES; - suffix = GIGABYTES; - } else { - suffix = MEGABYTES; - } - } - } - return String.valueOf(dec.format(fileSize) + suffix); - } - - /** - * Attempt to retrieve the thumbnail of given File from the MediaStore. This - * should not be called on the UI thread. - * - * @param context - * @param file - * @return - * @author paulburke - */ - public static Bitmap getThumbnail(Context context, File file) { - return getThumbnail(context, getUri(file), getMimeType(file)); - } - - /** - * Attempt to retrieve the thumbnail of given Uri from the MediaStore. This - * should not be called on the UI thread. - * - * @param context - * @param uri - * @return - * @author paulburke - */ - public static Bitmap getThumbnail(Context context, Uri uri) { - return getThumbnail(context, uri, getMimeType(context, uri)); - } - - /** - * Attempt to retrieve the thumbnail of given Uri from the MediaStore. This - * should not be called on the UI thread. - * - * @param context - * @param uri - * @param mimeType - * @return - * @author paulburke - */ - public static Bitmap getThumbnail(Context context, Uri uri, String mimeType) { - if (DEBUG) - Log.d(TAG, "Attempting to get thumbnail"); - - if (!isMediaUri(uri)) { - Log.e(TAG, "You can only retrieve thumbnails for images and videos."); - return null; - } - - Bitmap bm = null; - if (uri != null) { - final ContentResolver resolver = context.getContentResolver(); - Cursor cursor = null; - try { - cursor = resolver.query(uri, null, null, null, null); - if (cursor.moveToFirst()) { - final int id = cursor.getInt(0); - if (DEBUG) - Log.d(TAG, "Got thumb ID: " + id); - - if (mimeType.contains("video")) { - bm = MediaStore.Video.Thumbnails.getThumbnail( - resolver, - id, - MediaStore.Video.Thumbnails.MINI_KIND, - null); - } else if (mimeType.contains(FileUtils.MIME_TYPE_IMAGE)) { - bm = MediaStore.Images.Thumbnails.getThumbnail( - resolver, - id, - MediaStore.Images.Thumbnails.MINI_KIND, - null); - } - } - } catch (Exception e) { - if (DEBUG) - Log.e(TAG, "getThumbnail", e); - } finally { - if (cursor != null) - cursor.close(); - } - } - return bm; - } - - /** - * File and folder comparator. TODO Expose sorting option method - * - * @author paulburke - */ - public static Comparator sComparator = new Comparator() { - @Override - public int compare(File f1, File f2) { - // Sort alphabetically by lower case, which is much cleaner - return f1.getName().toLowerCase().compareTo( - f2.getName().toLowerCase()); - } - }; - - /** - * File (not directories) filter. - * - * @author paulburke - */ - public static FileFilter sFileFilter = new FileFilter() { - @Override - public boolean accept(File file) { - final String fileName = file.getName(); - // Return files only (not directories) and skip hidden files - return file.isFile() && !fileName.startsWith(HIDDEN_PREFIX); - } - }; - - /** - * Folder (directories) filter. - * - * @author paulburke - */ - public static FileFilter sDirFilter = new FileFilter() { - @Override - public boolean accept(File file) { - final String fileName = file.getName(); - // Return directories only and skip hidden directories - return file.isDirectory() && !fileName.startsWith(HIDDEN_PREFIX); - } - }; - - /** - * Get the Intent for selecting content to be used in an Intent Chooser. - * - * @return The intent for opening a file with Intent.createChooser() - * @author paulburke - */ - public static Intent createGetContentIntent() { - // Implicitly allow the user to select a particular kind of data - final Intent intent = new Intent(Intent.ACTION_GET_CONTENT); - // The MIME data type filter - intent.setType("*/*"); - // Only return URIs that can be opened with ContentResolver - intent.addCategory(Intent.CATEGORY_OPENABLE); - return intent; - } - - public static void copyFile(@NonNull String pathFrom, @NonNull String pathTo) throws IOException { - FileChannel outputChannel = null; - FileChannel inputChannel = null; - try { - inputChannel = new FileInputStream(new File(pathFrom)).getChannel(); - outputChannel = new FileOutputStream(new File(pathTo)).getChannel(); - inputChannel.transferTo(0, inputChannel.size(), outputChannel); - inputChannel.close(); - } finally { - if (inputChannel != null) inputChannel.close(); - if (outputChannel != null) outputChannel.close(); - } - - } - -} \ No newline at end of file diff --git a/library/src/main/java/com/yalantis/ucrop/util/ImageHeaderParser.java b/library/src/main/java/com/yalantis/ucrop/util/ImageHeaderParser.java deleted file mode 100755 index 6b476f4e..00000000 --- a/library/src/main/java/com/yalantis/ucrop/util/ImageHeaderParser.java +++ /dev/null @@ -1,420 +0,0 @@ -/* - * Copyright 2015 Google, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY GOOGLE, INC. ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of Google, Inc. - * - * Adapted for the uCrop library. - */ - -package com.yalantis.ucrop.util; - -import android.media.ExifInterface; -import android.text.TextUtils; -import android.util.Log; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.charset.Charset; - -/** - * A class for parsing the exif orientation from an image header. - */ -public class ImageHeaderParser { - private static final String TAG = "ImageHeaderParser"; - /** - * A constant indicating we were unable to parse the orientation from the image either because - * no exif segment containing orientation data existed, or because of an I/O error attempting to - * read the exif segment. - */ - public static final int UNKNOWN_ORIENTATION = -1; - - private static final int EXIF_MAGIC_NUMBER = 0xFFD8; - // "MM". - private static final int MOTOROLA_TIFF_MAGIC_NUMBER = 0x4D4D; - // "II". - private static final int INTEL_TIFF_MAGIC_NUMBER = 0x4949; - private static final String JPEG_EXIF_SEGMENT_PREAMBLE = "Exif\0\0"; - private static final byte[] JPEG_EXIF_SEGMENT_PREAMBLE_BYTES = - JPEG_EXIF_SEGMENT_PREAMBLE.getBytes(Charset.forName("UTF-8")); - private static final int SEGMENT_SOS = 0xDA; - private static final int MARKER_EOI = 0xD9; - private static final int SEGMENT_START_ID = 0xFF; - private static final int EXIF_SEGMENT_TYPE = 0xE1; - private static final int ORIENTATION_TAG_TYPE = 0x0112; - private static final int[] BYTES_PER_FORMAT = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8}; - - private final Reader reader; - - public ImageHeaderParser(InputStream is) { - reader = new StreamReader(is); - } - - /** - * Parse the orientation from the image header. If it doesn't handle this image type (or this is - * not an image) it will return a default value rather than throwing an exception. - * - * @return The exif orientation if present or -1 if the header couldn't be parsed or doesn't - * contain an orientation - * @throws IOException - */ - public int getOrientation() throws IOException { - final int magicNumber = reader.getUInt16(); - - if (!handles(magicNumber)) { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "Parser doesn't handle magic number: " + magicNumber); - } - return UNKNOWN_ORIENTATION; - } else { - int exifSegmentLength = moveToExifSegmentAndGetLength(); - if (exifSegmentLength == -1) { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "Failed to parse exif segment length, or exif segment not found"); - } - return UNKNOWN_ORIENTATION; - } - - byte[] exifData = new byte[exifSegmentLength]; - return parseExifSegment(exifData, exifSegmentLength); - } - } - - private int parseExifSegment(byte[] tempArray, int exifSegmentLength) throws IOException { - int read = reader.read(tempArray, exifSegmentLength); - if (read != exifSegmentLength) { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "Unable to read exif segment data" - + ", length: " + exifSegmentLength - + ", actually read: " + read); - } - return UNKNOWN_ORIENTATION; - } - - boolean hasJpegExifPreamble = hasJpegExifPreamble(tempArray, exifSegmentLength); - if (hasJpegExifPreamble) { - return parseExifSegment(new RandomAccessReader(tempArray, exifSegmentLength)); - } else { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "Missing jpeg exif preamble"); - } - return UNKNOWN_ORIENTATION; - } - } - - private boolean hasJpegExifPreamble(byte[] exifData, int exifSegmentLength) { - boolean result = - exifData != null && exifSegmentLength > JPEG_EXIF_SEGMENT_PREAMBLE_BYTES.length; - if (result) { - for (int i = 0; i < JPEG_EXIF_SEGMENT_PREAMBLE_BYTES.length; i++) { - if (exifData[i] != JPEG_EXIF_SEGMENT_PREAMBLE_BYTES[i]) { - result = false; - break; - } - } - } - return result; - } - - /** - * Moves reader to the start of the exif segment and returns the length of the exif segment or - * {@code -1} if no exif segment is found. - */ - private int moveToExifSegmentAndGetLength() throws IOException { - short segmentId, segmentType; - int segmentLength; - while (true) { - segmentId = reader.getUInt8(); - if (segmentId != SEGMENT_START_ID) { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "Unknown segmentId=" + segmentId); - } - return -1; - } - - segmentType = reader.getUInt8(); - - if (segmentType == SEGMENT_SOS) { - return -1; - } else if (segmentType == MARKER_EOI) { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "Found MARKER_EOI in exif segment"); - } - return -1; - } - - // Segment length includes bytes for segment length. - segmentLength = reader.getUInt16() - 2; - - if (segmentType != EXIF_SEGMENT_TYPE) { - long skipped = reader.skip(segmentLength); - if (skipped != segmentLength) { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "Unable to skip enough data" - + ", type: " + segmentType - + ", wanted to skip: " + segmentLength - + ", but actually skipped: " + skipped); - } - return -1; - } - } else { - return segmentLength; - } - } - } - - private static int parseExifSegment(RandomAccessReader segmentData) { - final int headerOffsetSize = JPEG_EXIF_SEGMENT_PREAMBLE.length(); - - short byteOrderIdentifier = segmentData.getInt16(headerOffsetSize); - final ByteOrder byteOrder; - if (byteOrderIdentifier == MOTOROLA_TIFF_MAGIC_NUMBER) { - byteOrder = ByteOrder.BIG_ENDIAN; - } else if (byteOrderIdentifier == INTEL_TIFF_MAGIC_NUMBER) { - byteOrder = ByteOrder.LITTLE_ENDIAN; - } else { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "Unknown endianness = " + byteOrderIdentifier); - } - byteOrder = ByteOrder.BIG_ENDIAN; - } - - segmentData.order(byteOrder); - - int firstIfdOffset = segmentData.getInt32(headerOffsetSize + 4) + headerOffsetSize; - int tagCount = segmentData.getInt16(firstIfdOffset); - - int tagOffset, tagType, formatCode, componentCount; - for (int i = 0; i < tagCount; i++) { - tagOffset = calcTagOffset(firstIfdOffset, i); - tagType = segmentData.getInt16(tagOffset); - - // We only want orientation. - if (tagType != ORIENTATION_TAG_TYPE) { - continue; - } - - formatCode = segmentData.getInt16(tagOffset + 2); - - // 12 is max format code. - if (formatCode < 1 || formatCode > 12) { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "Got invalid format code = " + formatCode); - } - continue; - } - - componentCount = segmentData.getInt32(tagOffset + 4); - - if (componentCount < 0) { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "Negative tiff component count"); - } - continue; - } - - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "Got tagIndex=" + i + " tagType=" + tagType + " formatCode=" + formatCode - + " componentCount=" + componentCount); - } - - final int byteCount = componentCount + BYTES_PER_FORMAT[formatCode]; - - if (byteCount > 4) { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "Got byte count > 4, not orientation, continuing, formatCode=" + formatCode); - } - continue; - } - - final int tagValueOffset = tagOffset + 8; - - if (tagValueOffset < 0 || tagValueOffset > segmentData.length()) { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "Illegal tagValueOffset=" + tagValueOffset + " tagType=" + tagType); - } - continue; - } - - if (byteCount < 0 || tagValueOffset + byteCount > segmentData.length()) { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "Illegal number of bytes for TI tag data tagType=" + tagType); - } - continue; - } - - //assume componentCount == 1 && fmtCode == 3 - return segmentData.getInt16(tagValueOffset); - } - - return -1; - } - - private static int calcTagOffset(int ifdOffset, int tagIndex) { - return ifdOffset + 2 + 12 * tagIndex; - } - - private static boolean handles(int imageMagicNumber) { - return (imageMagicNumber & EXIF_MAGIC_NUMBER) == EXIF_MAGIC_NUMBER - || imageMagicNumber == MOTOROLA_TIFF_MAGIC_NUMBER - || imageMagicNumber == INTEL_TIFF_MAGIC_NUMBER; - } - - private static class RandomAccessReader { - private final ByteBuffer data; - - public RandomAccessReader(byte[] data, int length) { - this.data = (ByteBuffer) ByteBuffer.wrap(data) - .order(ByteOrder.BIG_ENDIAN) - .limit(length); - } - - public void order(ByteOrder byteOrder) { - this.data.order(byteOrder); - } - - public int length() { - return data.remaining(); - } - - public int getInt32(int offset) { - return data.getInt(offset); - } - - public short getInt16(int offset) { - return data.getShort(offset); - } - } - - private interface Reader { - int getUInt16() throws IOException; - - short getUInt8() throws IOException; - - long skip(long total) throws IOException; - - int read(byte[] buffer, int byteCount) throws IOException; - } - - private static class StreamReader implements Reader { - private final InputStream is; - - // Motorola / big endian byte order. - public StreamReader(InputStream is) { - this.is = is; - } - - @Override - public int getUInt16() throws IOException { - return (is.read() << 8 & 0xFF00) | (is.read() & 0xFF); - } - - @Override - public short getUInt8() throws IOException { - return (short) (is.read() & 0xFF); - } - - @Override - public long skip(long total) throws IOException { - if (total < 0) { - return 0; - } - - long toSkip = total; - while (toSkip > 0) { - long skipped = is.skip(toSkip); - if (skipped > 0) { - toSkip -= skipped; - } else { - // Skip has no specific contract as to what happens when you reach the end of - // the stream. To differentiate between temporarily not having more data and - // having finished the stream, we read a single byte when we fail to skip any - // amount of data. - int testEofByte = is.read(); - if (testEofByte == -1) { - break; - } else { - toSkip--; - } - } - } - return total - toSkip; - } - - @Override - public int read(byte[] buffer, int byteCount) throws IOException { - int toRead = byteCount; - int read; - while (toRead > 0 && ((read = is.read(buffer, byteCount - toRead, toRead)) != -1)) { - toRead -= read; - } - return byteCount - toRead; - } - } - - public static void copyExif(ExifInterface originalExif, int width, int height, String imageOutputPath) throws IOException { - String[] attributes = new String[]{ - ExifInterface.TAG_APERTURE, - ExifInterface.TAG_DATETIME, - ExifInterface.TAG_DATETIME_DIGITIZED, - ExifInterface.TAG_EXPOSURE_TIME, - ExifInterface.TAG_FLASH, - ExifInterface.TAG_FOCAL_LENGTH, - ExifInterface.TAG_GPS_ALTITUDE, - ExifInterface.TAG_GPS_ALTITUDE_REF, - ExifInterface.TAG_GPS_DATESTAMP, - ExifInterface.TAG_GPS_LATITUDE, - ExifInterface.TAG_GPS_LATITUDE_REF, - ExifInterface.TAG_GPS_LONGITUDE, - ExifInterface.TAG_GPS_LONGITUDE_REF, - ExifInterface.TAG_GPS_PROCESSING_METHOD, - ExifInterface.TAG_GPS_TIMESTAMP, - ExifInterface.TAG_ISO, - ExifInterface.TAG_MAKE, - ExifInterface.TAG_MODEL, - ExifInterface.TAG_SUBSEC_TIME, - ExifInterface.TAG_SUBSEC_TIME_DIG, - ExifInterface.TAG_SUBSEC_TIME_ORIG, - ExifInterface.TAG_WHITE_BALANCE - }; - - ExifInterface newExif = new ExifInterface(imageOutputPath); - String value; - for (String attribute : attributes) { - value = originalExif.getAttribute(attribute); - if (!TextUtils.isEmpty(value)) { - newExif.setAttribute(attribute, value); - } - } - newExif.setAttribute(ExifInterface.TAG_IMAGE_WIDTH, String.valueOf(width)); - newExif.setAttribute(ExifInterface.TAG_IMAGE_LENGTH, String.valueOf(height)); - newExif.setAttribute(ExifInterface.TAG_ORIENTATION, "0"); - - newExif.saveAttributes(); - } - -} - diff --git a/library/src/main/java/com/yalantis/ucrop/util/RectUtils.java b/library/src/main/java/com/yalantis/ucrop/util/RectUtils.java deleted file mode 100755 index 867f8e06..00000000 --- a/library/src/main/java/com/yalantis/ucrop/util/RectUtils.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.yalantis.ucrop.util; - -import android.graphics.RectF; - -public class RectUtils { - - /** - * Gets a float array of the 2D coordinates representing a rectangles - * corners. - * The order of the corners in the float array is: - * 0------->1 - * ^ | - * | | - * | v - * 3<-------2 - * - * @param r the rectangle to get the corners of - * @return the float array of corners (8 floats) - */ - public static float[] getCornersFromRect(RectF r) { - return new float[]{ - r.left, r.top, - r.right, r.top, - r.right, r.bottom, - r.left, r.bottom - }; - } - - /** - * Gets a float array of two lengths representing a rectangles width and height - * The order of the corners in the input float array is: - * 0------->1 - * ^ | - * | | - * | v - * 3<-------2 - * - * @param corners the float array of corners (8 floats) - * @return the float array of width and height (2 floats) - */ - public static float[] getRectSidesFromCorners(float[] corners) { - return new float[]{(float) Math.sqrt(Math.pow(corners[0] - corners[2], 2) + Math.pow(corners[1] - corners[3], 2)), - (float) Math.sqrt(Math.pow(corners[2] - corners[4], 2) + Math.pow(corners[3] - corners[5], 2))}; - } - - public static float[] getCenterFromRect(RectF r) { - return new float[]{r.centerX(), r.centerY()}; - } - - /** - * Takes an array of 2D coordinates representing corners and returns the - * smallest rectangle containing those coordinates. - * - * @param array array of 2D coordinates - * @return smallest rectangle containing coordinates - */ - public static RectF trapToRect(float[] array) { - RectF r = new RectF(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, - Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY); - for (int i = 1; i < array.length; i += 2) { - float x = array[i - 1]; - float y = array[i]; - r.left = (x < r.left) ? x : r.left; - r.top = (y < r.top) ? y : r.top; - r.right = (x > r.right) ? x : r.right; - r.bottom = (y > r.bottom) ? y : r.bottom; - } - r.sort(); - return r; - } - -} \ No newline at end of file diff --git a/library/src/main/java/com/yalantis/ucrop/util/RotationGestureDetector.java b/library/src/main/java/com/yalantis/ucrop/util/RotationGestureDetector.java deleted file mode 100755 index 4fd8e5c3..00000000 --- a/library/src/main/java/com/yalantis/ucrop/util/RotationGestureDetector.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.yalantis.ucrop.util; - -import android.support.annotation.NonNull; -import android.view.MotionEvent; - -public class RotationGestureDetector { - - private static final int INVALID_POINTER_INDEX = -1; - - private float fX, fY, sX, sY; - - private int mPointerIndex1, mPointerIndex2; - private float mAngle; - private boolean mIsFirstTouch; - - private OnRotationGestureListener mListener; - - public RotationGestureDetector(OnRotationGestureListener listener) { - mListener = listener; - mPointerIndex1 = INVALID_POINTER_INDEX; - mPointerIndex2 = INVALID_POINTER_INDEX; - } - - public float getAngle() { - return mAngle; - } - - public boolean onTouchEvent(@NonNull MotionEvent event) { - switch (event.getActionMasked()) { - case MotionEvent.ACTION_DOWN: - sX = event.getX(); - sY = event.getY(); - mPointerIndex1 = event.findPointerIndex(event.getPointerId(0)); - mAngle = 0; - mIsFirstTouch = true; - break; - case MotionEvent.ACTION_POINTER_DOWN: - fX = event.getX(); - fY = event.getY(); - mPointerIndex2 = event.findPointerIndex(event.getPointerId(event.getActionIndex())); - mAngle = 0; - mIsFirstTouch = true; - break; - case MotionEvent.ACTION_MOVE: - if (mPointerIndex1 != INVALID_POINTER_INDEX && mPointerIndex2 != INVALID_POINTER_INDEX && event.getPointerCount() > mPointerIndex2) { - float nfX, nfY, nsX, nsY; - - nsX = event.getX(mPointerIndex1); - nsY = event.getY(mPointerIndex1); - nfX = event.getX(mPointerIndex2); - nfY = event.getY(mPointerIndex2); - - if (mIsFirstTouch) { - mAngle = 0; - mIsFirstTouch = false; - } else { - calculateAngleBetweenLines(fX, fY, sX, sY, nfX, nfY, nsX, nsY); - } - - if (mListener != null) { - mListener.onRotation(this); - } - fX = nfX; - fY = nfY; - sX = nsX; - sY = nsY; - } - break; - case MotionEvent.ACTION_UP: - mPointerIndex1 = INVALID_POINTER_INDEX; - break; - case MotionEvent.ACTION_POINTER_UP: - mPointerIndex2 = INVALID_POINTER_INDEX; - break; - } - return true; - } - - private float calculateAngleBetweenLines(float fx1, float fy1, float fx2, float fy2, - float sx1, float sy1, float sx2, float sy2) { - return calculateAngleDelta( - (float) Math.toDegrees((float) Math.atan2((fy1 - fy2), (fx1 - fx2))), - (float) Math.toDegrees((float) Math.atan2((sy1 - sy2), (sx1 - sx2)))); - } - - private float calculateAngleDelta(float angleFrom, float angleTo) { - mAngle = angleTo % 360.0f - angleFrom % 360.0f; - - if (mAngle < -180.0f) { - mAngle += 360.0f; - } else if (mAngle > 180.0f) { - mAngle -= 360.0f; - } - - return mAngle; - } - - public static class SimpleOnRotationGestureListener implements OnRotationGestureListener { - - @Override - public boolean onRotation(RotationGestureDetector rotationDetector) { - return false; - } - } - - public interface OnRotationGestureListener { - - boolean onRotation(RotationGestureDetector rotationDetector); - } - -} \ No newline at end of file diff --git a/library/src/main/java/com/yalantis/ucrop/util/SelectedStateListDrawable.java b/library/src/main/java/com/yalantis/ucrop/util/SelectedStateListDrawable.java deleted file mode 100755 index 825fec75..00000000 --- a/library/src/main/java/com/yalantis/ucrop/util/SelectedStateListDrawable.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.yalantis.ucrop.util; - -import android.graphics.PorterDuff; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.StateListDrawable; - -/** - * Hack class to properly support state drawable back to Android 1.6 - */ -public class SelectedStateListDrawable extends StateListDrawable { - - private int mSelectionColor; - - public SelectedStateListDrawable(Drawable drawable, int selectionColor) { - super(); - this.mSelectionColor = selectionColor; - addState(new int[]{android.R.attr.state_selected}, drawable); - addState(new int[]{}, drawable); - } - - @Override - protected boolean onStateChange(int[] states) { - boolean isStatePressedInArray = false; - for (int state : states) { - if (state == android.R.attr.state_selected) { - isStatePressedInArray = true; - } - } - if (isStatePressedInArray) { - super.setColorFilter(mSelectionColor, PorterDuff.Mode.SRC_ATOP); - } else { - super.clearColorFilter(); - } - return super.onStateChange(states); - } - - @Override - public boolean isStateful() { - return true; - } - -} diff --git a/library/src/main/java/com/yalantis/ucrop/view/CropImageView.java b/library/src/main/java/com/yalantis/ucrop/view/CropImageView.java deleted file mode 100755 index e19d2476..00000000 --- a/library/src/main/java/com/yalantis/ucrop/view/CropImageView.java +++ /dev/null @@ -1,622 +0,0 @@ -package com.yalantis.ucrop.view; - -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Bitmap; -import android.graphics.Matrix; -import android.graphics.RectF; -import android.graphics.drawable.Drawable; -import android.support.annotation.IntRange; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.util.AttributeSet; - -import com.yalantis.ucrop.callback.BitmapCropCallback; -import com.yalantis.ucrop.callback.CropBoundsChangeListener; -import com.yalantis.ucrop.model.CropParameters; -import com.yalantis.ucrop.model.ImageState; -import com.yalantis.ucrop.task.BitmapCropTask; -import com.yalantis.ucrop.util.CubicEasing; -import com.yalantis.ucrop.util.RectUtils; - -import java.lang.ref.WeakReference; -import java.util.Arrays; - -import cn.finalteam.rxgalleryfinal.R; - -/** - * Created by Oleksii Shliama (https://github.com/shliama). - *

- * This class adds crop feature, methods to draw crop guidelines, and keep image in correct state. - * Also it extends parent class methods to add checks for scale; animating zoom in/out. - */ -public class CropImageView extends TransformImageView { - - public static final int DEFAULT_MAX_BITMAP_SIZE = 0; - public static final int DEFAULT_IMAGE_TO_CROP_BOUNDS_ANIM_DURATION = 500; - public static final float DEFAULT_MAX_SCALE_MULTIPLIER = 10.0f; - public static final float SOURCE_IMAGE_ASPECT_RATIO = 0f; - public static final float DEFAULT_ASPECT_RATIO = SOURCE_IMAGE_ASPECT_RATIO; - - private final RectF mCropRect = new RectF(); - - private final Matrix mTempMatrix = new Matrix(); - - private float mTargetAspectRatio; - private float mMaxScaleMultiplier = DEFAULT_MAX_SCALE_MULTIPLIER; - - private CropBoundsChangeListener mCropBoundsChangeListener; - - private Runnable mWrapCropBoundsRunnable, mZoomImageToPositionRunnable = null; - - private float mMaxScale, mMinScale; - private int mMaxResultImageSizeX = 0, mMaxResultImageSizeY = 0; - private long mImageToWrapCropBoundsAnimDuration = DEFAULT_IMAGE_TO_CROP_BOUNDS_ANIM_DURATION; - - 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); - } - - /** - * Cancels all current animations and sets image to fill crop area (without animation). - * Then creates and executes {@link BitmapCropTask} with proper parameters. - */ - public void cropAndSaveImage(@NonNull Bitmap.CompressFormat compressFormat, int compressQuality, - @Nullable BitmapCropCallback cropCallback) { - cancelAllAnimations(); - setImageToWrapCropBounds(false); - - final ImageState imageState = new ImageState( - mCropRect, RectUtils.trapToRect(mCurrentImageCorners), - getCurrentScale(), getCurrentAngle()); - - final CropParameters cropParameters = new CropParameters( - mMaxResultImageSizeX, mMaxResultImageSizeY, - compressFormat, compressQuality, - getImageInputPath(), getImageOutputPath(), getExifInfo()); - - new BitmapCropTask(getViewBitmap(), imageState, cropParameters, cropCallback).execute(); - } - - /** - * @return - maximum scale value for current image and crop ratio - */ - public float getMaxScale() { - return mMaxScale; - } - - /** - * @return - minimum scale value for current image and crop ratio - */ - public float getMinScale() { - return mMinScale; - } - - /** - * @return - aspect ratio for crop bounds - */ - public float getTargetAspectRatio() { - return mTargetAspectRatio; - } - - /** - * Updates current crop rectangle with given. Also recalculates image properties and position - * to fit new crop rectangle. - * - * @param cropRect - new crop rectangle - */ - public void setCropRect(RectF cropRect) { - mCropRect.set(cropRect.left - getPaddingLeft(), cropRect.top - getPaddingTop(), - cropRect.right - getPaddingRight(), cropRect.bottom - getPaddingBottom()); - calculateImageScaleBounds(); - setImageToWrapCropBounds(); - } - - /** - * This method sets aspect ratio for crop bounds. - * If {@link #SOURCE_IMAGE_ASPECT_RATIO} value is passed - aspect ratio is calculated - * based on current image width and height. - * - * @param targetAspectRatio - aspect ratio for image crop (e.g. 1.77(7) for 16:9) - */ - public void setTargetAspectRatio(float targetAspectRatio) { - final Drawable drawable = getDrawable(); - if (drawable == null) { - mTargetAspectRatio = targetAspectRatio; - return; - } - - if (targetAspectRatio == SOURCE_IMAGE_ASPECT_RATIO) { - mTargetAspectRatio = drawable.getIntrinsicWidth() / (float) drawable.getIntrinsicHeight(); - } else { - mTargetAspectRatio = targetAspectRatio; - } - - if (mCropBoundsChangeListener != null) { - mCropBoundsChangeListener.onCropAspectRatioChanged(mTargetAspectRatio); - } - } - - @Nullable - public CropBoundsChangeListener getCropBoundsChangeListener() { - return mCropBoundsChangeListener; - } - - public void setCropBoundsChangeListener(@Nullable CropBoundsChangeListener cropBoundsChangeListener) { - mCropBoundsChangeListener = cropBoundsChangeListener; - } - - /** - * This method sets maximum width for resulting cropped image - * - * @param maxResultImageSizeX - size in pixels - */ - public void setMaxResultImageSizeX(@IntRange(from = 10) int maxResultImageSizeX) { - mMaxResultImageSizeX = maxResultImageSizeX; - } - - /** - * This method sets maximum width for resulting cropped image - * - * @param maxResultImageSizeY - size in pixels - */ - public void setMaxResultImageSizeY(@IntRange(from = 10) int maxResultImageSizeY) { - mMaxResultImageSizeY = maxResultImageSizeY; - } - - /** - * This method sets animation duration for image to wrap the crop bounds - * - * @param imageToWrapCropBoundsAnimDuration - duration in milliseconds - */ - public void setImageToWrapCropBoundsAnimDuration(@IntRange(from = 100) long imageToWrapCropBoundsAnimDuration) { - if (imageToWrapCropBoundsAnimDuration > 0) { - mImageToWrapCropBoundsAnimDuration = imageToWrapCropBoundsAnimDuration; - } else { - throw new IllegalArgumentException("Animation duration cannot be negative value."); - } - } - - /** - * This method sets multiplier that is used to calculate max image scale from min image scale. - * - * @param maxScaleMultiplier - (minScale * maxScaleMultiplier) = maxScale - */ - public void setMaxScaleMultiplier(float maxScaleMultiplier) { - mMaxScaleMultiplier = maxScaleMultiplier; - } - - /** - * This method scales image down for given value related to image center. - */ - public void zoomOutImage(float deltaScale) { - zoomOutImage(deltaScale, mCropRect.centerX(), mCropRect.centerY()); - } - - /** - * This method scales image down for given value related given coords (x, y). - */ - public void zoomOutImage(float scale, float centerX, float centerY) { - if (scale >= getMinScale()) { - postScale(scale / getCurrentScale(), centerX, centerY); - } - } - - /** - * This method scales image up for given value related to image center. - */ - public void zoomInImage(float deltaScale) { - zoomInImage(deltaScale, mCropRect.centerX(), mCropRect.centerY()); - } - - /** - * This method scales image up for given value related to given coords (x, y). - */ - public void zoomInImage(float scale, float centerX, float centerY) { - if (scale <= getMaxScale()) { - postScale(scale / getCurrentScale(), centerX, centerY); - } - } - - /** - * This method changes image scale for given value related to point (px, py) but only if - * resulting scale is in min/max bounds. - * - * @param deltaScale - scale value - * @param px - scale center X - * @param py - scale center Y - */ - public void postScale(float deltaScale, float px, float py) { - if (deltaScale > 1 && getCurrentScale() * deltaScale <= getMaxScale()) { - super.postScale(deltaScale, px, py); - } else if (deltaScale < 1 && getCurrentScale() * deltaScale >= getMinScale()) { - super.postScale(deltaScale, px, py); - } - } - - /** - * This method rotates image for given angle related to the image center. - * - * @param deltaAngle - angle to rotate - */ - public void postRotate(float deltaAngle) { - postRotate(deltaAngle, mCropRect.centerX(), mCropRect.centerY()); - } - - /** - * This method cancels all current Runnable objects that represent animations. - */ - public void cancelAllAnimations() { - removeCallbacks(mWrapCropBoundsRunnable); - removeCallbacks(mZoomImageToPositionRunnable); - } - - public void setImageToWrapCropBounds() { - setImageToWrapCropBounds(true); - } - - /** - * If image doesn't fill the crop bounds it must be translated and scaled properly to fill those. - *

- * Therefore this method calculates delta X, Y and scale values and passes them to the - * {@link WrapCropBoundsRunnable} which animates image. - * Scale value must be calculated only if image won't fill the crop bounds after it's translated to the - * crop bounds rectangle center. Using temporary variables this method checks this case. - */ - public void setImageToWrapCropBounds(boolean animate) { - if (mBitmapLaidOut && !isImageWrapCropBounds()) { - - float currentX = mCurrentImageCenter[0]; - float currentY = mCurrentImageCenter[1]; - float currentScale = getCurrentScale(); - - float deltaX = mCropRect.centerX() - currentX; - float deltaY = mCropRect.centerY() - currentY; - float deltaScale = 0; - - mTempMatrix.reset(); - mTempMatrix.setTranslate(deltaX, deltaY); - - final float[] tempCurrentImageCorners = Arrays.copyOf(mCurrentImageCorners, mCurrentImageCorners.length); - mTempMatrix.mapPoints(tempCurrentImageCorners); - - boolean willImageWrapCropBoundsAfterTranslate = isImageWrapCropBounds(tempCurrentImageCorners); - - if (willImageWrapCropBoundsAfterTranslate) { - final float[] imageIndents = calculateImageIndents(); - deltaX = -(imageIndents[0] + imageIndents[2]); - deltaY = -(imageIndents[1] + imageIndents[3]); - } else { - RectF tempCropRect = new RectF(mCropRect); - mTempMatrix.reset(); - mTempMatrix.setRotate(getCurrentAngle()); - mTempMatrix.mapRect(tempCropRect); - - final float[] currentImageSides = RectUtils.getRectSidesFromCorners(mCurrentImageCorners); - - deltaScale = Math.max(tempCropRect.width() / currentImageSides[0], - tempCropRect.height() / currentImageSides[1]); - deltaScale = deltaScale * currentScale - currentScale; - } - - if (animate) { - post(mWrapCropBoundsRunnable = new WrapCropBoundsRunnable( - CropImageView.this, mImageToWrapCropBoundsAnimDuration, currentX, currentY, deltaX, deltaY, - currentScale, deltaScale, willImageWrapCropBoundsAfterTranslate)); - } else { - postTranslate(deltaX, deltaY); - if (!willImageWrapCropBoundsAfterTranslate) { - zoomInImage(currentScale + deltaScale, mCropRect.centerX(), mCropRect.centerY()); - } - } - } - } - - /** - * First, un-rotate image and crop rectangles (make image rectangle axis-aligned). - * Second, calculate deltas between those rectangles sides. - * Third, depending on delta (its sign) put them or zero inside an array. - * Fourth, using Matrix, rotate back those points (indents). - * - * @return - the float array of image indents (4 floats) - in this order [left, top, right, bottom] - */ - private float[] calculateImageIndents() { - mTempMatrix.reset(); - mTempMatrix.setRotate(-getCurrentAngle()); - - float[] unrotatedImageCorners = Arrays.copyOf(mCurrentImageCorners, mCurrentImageCorners.length); - float[] unrotatedCropBoundsCorners = RectUtils.getCornersFromRect(mCropRect); - - mTempMatrix.mapPoints(unrotatedImageCorners); - mTempMatrix.mapPoints(unrotatedCropBoundsCorners); - - RectF unrotatedImageRect = RectUtils.trapToRect(unrotatedImageCorners); - RectF unrotatedCropRect = RectUtils.trapToRect(unrotatedCropBoundsCorners); - - float deltaLeft = unrotatedImageRect.left - unrotatedCropRect.left; - float deltaTop = unrotatedImageRect.top - unrotatedCropRect.top; - float deltaRight = unrotatedImageRect.right - unrotatedCropRect.right; - float deltaBottom = unrotatedImageRect.bottom - unrotatedCropRect.bottom; - - float indents[] = new float[4]; - indents[0] = (deltaLeft > 0) ? deltaLeft : 0; - indents[1] = (deltaTop > 0) ? deltaTop : 0; - indents[2] = (deltaRight < 0) ? deltaRight : 0; - indents[3] = (deltaBottom < 0) ? deltaBottom : 0; - - mTempMatrix.reset(); - mTempMatrix.setRotate(getCurrentAngle()); - mTempMatrix.mapPoints(indents); - - return indents; - } - - /** - * When image is laid out it must be centered properly to fit current crop bounds. - */ - @Override - protected void onImageLaidOut() { - super.onImageLaidOut(); - final Drawable drawable = getDrawable(); - if (drawable == null) { - return; - } - - float drawableWidth = drawable.getIntrinsicWidth(); - float drawableHeight = drawable.getIntrinsicHeight(); - - if (mTargetAspectRatio == SOURCE_IMAGE_ASPECT_RATIO) { - mTargetAspectRatio = drawableWidth / drawableHeight; - } - - int height = (int) (mThisWidth / mTargetAspectRatio); - if (height > mThisHeight) { - int width = (int) (mThisHeight * mTargetAspectRatio); - int halfDiff = (mThisWidth - width) / 2; - mCropRect.set(halfDiff, 0, width + halfDiff, mThisHeight); - } else { - int halfDiff = (mThisHeight - height) / 2; - mCropRect.set(0, halfDiff, mThisWidth, height + halfDiff); - } - - calculateImageScaleBounds(drawableWidth, drawableHeight); - setupInitialImagePosition(drawableWidth, drawableHeight); - - if (mCropBoundsChangeListener != null) { - mCropBoundsChangeListener.onCropAspectRatioChanged(mTargetAspectRatio); - } - if (mTransformImageListener != null) { - mTransformImageListener.onScale(getCurrentScale()); - mTransformImageListener.onRotate(getCurrentAngle()); - } - } - - /** - * This method checks whether current image fills the crop bounds. - */ - protected boolean isImageWrapCropBounds() { - return isImageWrapCropBounds(mCurrentImageCorners); - } - - /** - * This methods checks whether a rectangle that is represented as 4 corner points (8 floats) - * fills the crop bounds rectangle. - * - * @param imageCorners - corners of a rectangle - * @return - true if it wraps crop bounds, false - otherwise - */ - protected boolean isImageWrapCropBounds(float[] imageCorners) { - mTempMatrix.reset(); - mTempMatrix.setRotate(-getCurrentAngle()); - - float[] unrotatedImageCorners = Arrays.copyOf(imageCorners, imageCorners.length); - mTempMatrix.mapPoints(unrotatedImageCorners); - - float[] unrotatedCropBoundsCorners = RectUtils.getCornersFromRect(mCropRect); - mTempMatrix.mapPoints(unrotatedCropBoundsCorners); - - return RectUtils.trapToRect(unrotatedImageCorners).contains(RectUtils.trapToRect(unrotatedCropBoundsCorners)); - } - - /** - * This method changes image scale (animating zoom for given duration), related to given center (x,y). - * - * @param scale - target scale - * @param centerX - scale center X - * @param centerY - scale center Y - * @param durationMs - zoom animation duration - */ - protected void zoomImageToPosition(float scale, float centerX, float centerY, long durationMs) { - if (scale > getMaxScale()) { - scale = getMaxScale(); - } - - final float oldScale = getCurrentScale(); - final float deltaScale = scale - oldScale; - - post(mZoomImageToPositionRunnable = new ZoomImageToPosition(CropImageView.this, - durationMs, oldScale, deltaScale, centerX, centerY)); - } - - private void calculateImageScaleBounds() { - final Drawable drawable = getDrawable(); - if (drawable == null) { - return; - } - calculateImageScaleBounds(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); - } - - /** - * This method calculates image minimum and maximum scale values for current {@link #mCropRect}. - * - * @param drawableWidth - image width - * @param drawableHeight - image height - */ - private void calculateImageScaleBounds(float drawableWidth, float drawableHeight) { - float widthScale = mCropRect.width() / drawableWidth; - float heightScale = mCropRect.height() / drawableHeight; - - mMinScale = Math.max(widthScale, heightScale); - mMaxScale = mMinScale * mMaxScaleMultiplier; - } - - /** - * This method calculates initial image position so it is positioned properly. - * Then it sets those values to the current image matrix. - * - * @param drawableWidth - image width - * @param drawableHeight - image height - */ - private void setupInitialImagePosition(float drawableWidth, float drawableHeight) { - float cropRectWidth = mCropRect.width(); - float cropRectHeight = mCropRect.height(); - - float tw = (cropRectWidth - drawableWidth * mMinScale) / 2.0f + mCropRect.left; - float th = (cropRectHeight - drawableHeight * mMinScale) / 2.0f + mCropRect.top; - - mCurrentImageMatrix.reset(); - mCurrentImageMatrix.postScale(mMinScale, mMinScale); - mCurrentImageMatrix.postTranslate(tw, th); - setImageMatrix(mCurrentImageMatrix); - } - - /** - * This method extracts all needed values from the styled attributes. - * Those are used to configure the view. - */ - @SuppressWarnings("deprecation") - protected void processStyledAttributes(@NonNull TypedArray a) { - float targetAspectRatioX = Math.abs(a.getFloat(R.styleable.gallery_ucrop_UCropView_gallery_ucrop_aspect_ratio_x, DEFAULT_ASPECT_RATIO)); - float targetAspectRatioY = Math.abs(a.getFloat(R.styleable.gallery_ucrop_UCropView_gallery_ucrop_aspect_ratio_y, DEFAULT_ASPECT_RATIO)); - - if (targetAspectRatioX == SOURCE_IMAGE_ASPECT_RATIO || targetAspectRatioY == SOURCE_IMAGE_ASPECT_RATIO) { - mTargetAspectRatio = SOURCE_IMAGE_ASPECT_RATIO; - } else { - mTargetAspectRatio = targetAspectRatioX / targetAspectRatioY; - } - } - - /** - * This Runnable is used to animate an image so it fills the crop bounds entirely. - * Given values are interpolated during the animation time. - * Runnable can be terminated either vie {@link #cancelAllAnimations()} method - * or when certain conditions inside {@link WrapCropBoundsRunnable#run()} method are triggered. - */ - private static class WrapCropBoundsRunnable implements Runnable { - - private final WeakReference mCropImageView; - - private final long mDurationMs, mStartTime; - private final float mOldX, mOldY; - private final float mCenterDiffX, mCenterDiffY; - private final float mOldScale; - private final float mDeltaScale; - private final boolean mWillBeImageInBoundsAfterTranslate; - - public WrapCropBoundsRunnable(CropImageView cropImageView, - long durationMs, - float oldX, float oldY, - float centerDiffX, float centerDiffY, - float oldScale, float deltaScale, - boolean willBeImageInBoundsAfterTranslate) { - - mCropImageView = new WeakReference<>(cropImageView); - - mDurationMs = durationMs; - mStartTime = System.currentTimeMillis(); - mOldX = oldX; - mOldY = oldY; - mCenterDiffX = centerDiffX; - mCenterDiffY = centerDiffY; - mOldScale = oldScale; - mDeltaScale = deltaScale; - mWillBeImageInBoundsAfterTranslate = willBeImageInBoundsAfterTranslate; - } - - @Override - public void run() { - CropImageView cropImageView = mCropImageView.get(); - if (cropImageView == null) { - return; - } - - long now = System.currentTimeMillis(); - float currentMs = Math.min(mDurationMs, now - mStartTime); - - float newX = CubicEasing.easeOut(currentMs, 0, mCenterDiffX, mDurationMs); - float newY = CubicEasing.easeOut(currentMs, 0, mCenterDiffY, mDurationMs); - float newScale = CubicEasing.easeInOut(currentMs, 0, mDeltaScale, mDurationMs); - - if (currentMs < mDurationMs) { - cropImageView.postTranslate(newX - (cropImageView.mCurrentImageCenter[0] - mOldX), newY - (cropImageView.mCurrentImageCenter[1] - mOldY)); - if (!mWillBeImageInBoundsAfterTranslate) { - cropImageView.zoomInImage(mOldScale + newScale, cropImageView.mCropRect.centerX(), cropImageView.mCropRect.centerY()); - } - if (!cropImageView.isImageWrapCropBounds()) { - cropImageView.post(this); - } - } - } - } - - /** - * This Runnable is used to animate an image zoom. - * Given values are interpolated during the animation time. - * Runnable can be terminated either vie {@link #cancelAllAnimations()} method - * or when certain conditions inside {@link ZoomImageToPosition#run()} method are triggered. - */ - private static class ZoomImageToPosition implements Runnable { - - private final WeakReference mCropImageView; - - private final long mDurationMs, mStartTime; - private final float mOldScale; - private final float mDeltaScale; - private final float mDestX; - private final float mDestY; - - public ZoomImageToPosition(CropImageView cropImageView, - long durationMs, - float oldScale, float deltaScale, - float destX, float destY) { - - mCropImageView = new WeakReference<>(cropImageView); - - mStartTime = System.currentTimeMillis(); - mDurationMs = durationMs; - mOldScale = oldScale; - mDeltaScale = deltaScale; - mDestX = destX; - mDestY = destY; - } - - @Override - public void run() { - CropImageView cropImageView = mCropImageView.get(); - if (cropImageView == null) { - return; - } - - long now = System.currentTimeMillis(); - float currentMs = Math.min(mDurationMs, now - mStartTime); - float newScale = CubicEasing.easeInOut(currentMs, 0, mDeltaScale, mDurationMs); - - if (currentMs < mDurationMs) { - cropImageView.zoomInImage(mOldScale + newScale, mDestX, mDestY); - cropImageView.post(this); - } else { - cropImageView.setImageToWrapCropBounds(); - } - } - - } - -} diff --git a/library/src/main/java/com/yalantis/ucrop/view/GestureCropImageView.java b/library/src/main/java/com/yalantis/ucrop/view/GestureCropImageView.java deleted file mode 100755 index b0f3cff9..00000000 --- a/library/src/main/java/com/yalantis/ucrop/view/GestureCropImageView.java +++ /dev/null @@ -1,152 +0,0 @@ -package com.yalantis.ucrop.view; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.GestureDetector; -import android.view.MotionEvent; -import android.view.ScaleGestureDetector; - -import com.yalantis.ucrop.util.RotationGestureDetector; - -/** - * Created by Oleksii Shliama (https://github.com/shliama). - */ -public class GestureCropImageView extends CropImageView { - - private static final int DOUBLE_TAP_ZOOM_DURATION = 200; - - private ScaleGestureDetector mScaleDetector; - private RotationGestureDetector mRotateDetector; - private GestureDetector mGestureDetector; - - private float mMidPntX, mMidPntY; - - private boolean mIsRotateEnabled = true, mIsScaleEnabled = true; - private int mDoubleTapScaleSteps = 5; - - public GestureCropImageView(Context context) { - super(context); - } - - public GestureCropImageView(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public GestureCropImageView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - public void setScaleEnabled(boolean scaleEnabled) { - mIsScaleEnabled = scaleEnabled; - } - - public boolean isScaleEnabled() { - return mIsScaleEnabled; - } - - public void setRotateEnabled(boolean rotateEnabled) { - mIsRotateEnabled = rotateEnabled; - } - - public boolean isRotateEnabled() { - return mIsRotateEnabled; - } - - public void setDoubleTapScaleSteps(int doubleTapScaleSteps) { - mDoubleTapScaleSteps = doubleTapScaleSteps; - } - - public int getDoubleTapScaleSteps() { - return mDoubleTapScaleSteps; - } - - /** - * If it's ACTION_DOWN event - user touches the screen and all current animation must be canceled. - * If it's ACTION_UP event - user removed all fingers from the screen and current image position must be corrected. - * If there are more than 2 fingers - update focal point coordinates. - * Pass the event to the gesture detectors if those are enabled. - */ - @Override - public boolean onTouchEvent(MotionEvent event) { - if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN) { - cancelAllAnimations(); - } - - if (event.getPointerCount() > 1) { - mMidPntX = (event.getX(0) + event.getX(1)) / 2; - mMidPntY = (event.getY(0) + event.getY(1)) / 2; - } - - mGestureDetector.onTouchEvent(event); - - if (mIsScaleEnabled) { - mScaleDetector.onTouchEvent(event); - } - - if (mIsRotateEnabled) { - mRotateDetector.onTouchEvent(event); - } - - if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP) { - setImageToWrapCropBounds(); - } - return true; - } - - @Override - protected void init() { - super.init(); - setupGestureListeners(); - } - - /** - * This method calculates target scale value for double tap gesture. - * User is able to zoom the image from min scale value - * to the max scale value with {@link #mDoubleTapScaleSteps} double taps. - */ - protected float getDoubleTapTargetScale() { - return getCurrentScale() * (float) Math.pow(getMaxScale() / getMinScale(), 1.0f / mDoubleTapScaleSteps); - } - - private void setupGestureListeners() { - mGestureDetector = new GestureDetector(getContext(), new GestureListener(), null, true); - mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener()); - mRotateDetector = new RotationGestureDetector(new RotateListener()); - } - - private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { - - @Override - public boolean onScale(ScaleGestureDetector detector) { - postScale(detector.getScaleFactor(), mMidPntX, mMidPntY); - return true; - } - } - - private class GestureListener extends GestureDetector.SimpleOnGestureListener { - - @Override - public boolean onDoubleTap(MotionEvent e) { - zoomImageToPosition(getDoubleTapTargetScale(), e.getX(), e.getY(), DOUBLE_TAP_ZOOM_DURATION); - return super.onDoubleTap(e); - } - - @Override - public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { - postTranslate(-distanceX, -distanceY); - return true; - } - - } - - private class RotateListener extends RotationGestureDetector.SimpleOnRotationGestureListener { - - @Override - public boolean onRotation(RotationGestureDetector rotationDetector) { - postRotate(rotationDetector.getAngle(), mMidPntX, mMidPntY); - return true; - } - - } - -} diff --git a/library/src/main/java/com/yalantis/ucrop/view/OverlayView.java b/library/src/main/java/com/yalantis/ucrop/view/OverlayView.java deleted file mode 100755 index 31cff934..00000000 --- a/library/src/main/java/com/yalantis/ucrop/view/OverlayView.java +++ /dev/null @@ -1,485 +0,0 @@ -package com.yalantis.ucrop.view; - -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.RectF; -import android.graphics.Region; -import android.os.Build; -import android.support.annotation.ColorInt; -import android.support.annotation.IntRange; -import android.support.annotation.NonNull; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; - -import com.yalantis.ucrop.callback.OverlayViewChangeListener; -import com.yalantis.ucrop.util.RectUtils; - -import cn.finalteam.rxgalleryfinal.R; - -/** - * Created by Oleksii Shliama (https://github.com/shliama). - *

- * This view is used for drawing the overlay on top of the image. It may have frame, crop guidelines and dimmed area. - * This must have LAYER_TYPE_SOFTWARE to draw itself properly. - */ -public class OverlayView extends View { - - public static final boolean DEFAULT_SHOW_CROP_FRAME = true; - public static final boolean DEFAULT_SHOW_CROP_GRID = true; - public static final boolean DEFAULT_OVAL_DIMMED_LAYER = false; - public static final boolean DEFAULT_FREESTYLE_CROP_ENABLED = false; - public static final int DEFAULT_CROP_GRID_ROW_COUNT = 2; - public static final int DEFAULT_CROP_GRID_COLUMN_COUNT = 2; - - private final RectF mCropViewRect = new RectF(); - private final RectF mTempRect = new RectF(); - - private int mCropGridRowCount, mCropGridColumnCount; - private float mTargetAspectRatio; - private float[] mGridPoints = null; - private boolean mShowCropFrame, mShowCropGrid; - private boolean mOvalDimmedLayer; - private int mDimmedColor; - private Path mCircularPath = new Path(); - private Paint mDimmedStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG); - private Paint mCropGridPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - private Paint mCropFramePaint = new Paint(Paint.ANTI_ALIAS_FLAG); - private Paint mCropFrameCornersPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - - protected int mThisWidth, mThisHeight; - - private boolean mIsFreestyleCropEnabled = DEFAULT_FREESTYLE_CROP_ENABLED; - protected float[] mCropGridCorners; - private int mCurrentTouchCornerIndex = -1; - private int mTouchPointThreshold; - private int mCropRectMinSize; - private int mCropRectCornerTouchAreaLineLength; - - private OverlayViewChangeListener mCallback; - - { - mTouchPointThreshold = getResources().getDimensionPixelSize(R.dimen.gallery_ucrop_default_crop_rect_corner_touch_threshold); - mCropRectMinSize = getResources().getDimensionPixelSize(R.dimen.gallery_ucrop_default_crop_rect_min_size); - mCropRectCornerTouchAreaLineLength = getResources().getDimensionPixelSize(R.dimen.gallery_ucrop_default_crop_rect_corner_touch_area_line_length); - } - - public OverlayView(Context context) { - this(context, null); - } - - public OverlayView(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public OverlayView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - init(); - } - - public OverlayViewChangeListener getOverlayViewChangeListener() { - return mCallback; - } - - public void setOverlayViewChangeListener(OverlayViewChangeListener callback) { - mCallback = callback; - } - - @NonNull - public RectF getCropViewRect() { - return mCropViewRect; - } - - public boolean isFreestyleCropEnabled() { - return mIsFreestyleCropEnabled; - } - - public void setFreestyleCropEnabled(boolean freestyleCropEnabled) { - mIsFreestyleCropEnabled = freestyleCropEnabled; - } - - /** - * Setter for {@link #mOvalDimmedLayer} variable. - * - * @param ovalDimmedLayer - set it to true if you want dimmed layer to be an oval - */ - public void setOvalDimmedLayer(boolean ovalDimmedLayer) { - mOvalDimmedLayer = ovalDimmedLayer; - } - - /** - * Setter for crop grid rows count. - * Resets {@link #mGridPoints} variable because it is not valid anymore. - */ - public void setCropGridRowCount(@IntRange(from = 0) int cropGridRowCount) { - mCropGridRowCount = cropGridRowCount; - mGridPoints = null; - } - - /** - * Setter for crop grid columns count. - * Resets {@link #mGridPoints} variable because it is not valid anymore. - */ - public void setCropGridColumnCount(@IntRange(from = 0) int cropGridColumnCount) { - mCropGridColumnCount = cropGridColumnCount; - mGridPoints = null; - } - - /** - * Setter for {@link #mShowCropFrame} variable. - * - * @param showCropFrame - set to true if you want to see a crop frame rectangle on top of an image - */ - public void setShowCropFrame(boolean showCropFrame) { - mShowCropFrame = showCropFrame; - } - - /** - * Setter for {@link #mShowCropGrid} variable. - * - * @param showCropGrid - set to true if you want to see a crop grid on top of an image - */ - public void setShowCropGrid(boolean showCropGrid) { - mShowCropGrid = showCropGrid; - } - - /** - * Setter for {@link #mDimmedColor} variable. - * - * @param dimmedColor - desired color of dimmed area around the crop bounds - */ - public void setDimmedColor(@ColorInt int dimmedColor) { - mDimmedColor = dimmedColor; - } - - /** - * Setter for crop frame stroke width - */ - public void setCropFrameStrokeWidth(@IntRange(from = 0) int width) { - mCropFramePaint.setStrokeWidth(width); - } - - /** - * Setter for crop grid stroke width - */ - public void setCropGridStrokeWidth(@IntRange(from = 0) int width) { - mCropGridPaint.setStrokeWidth(width); - } - - /** - * Setter for crop frame color - */ - public void setCropFrameColor(@ColorInt int color) { - mCropFramePaint.setColor(color); - } - - /** - * Setter for crop grid color - */ - public void setCropGridColor(@ColorInt int color) { - mCropGridPaint.setColor(color); - } - - /** - * This method sets aspect ratio for crop bounds. - * - * @param targetAspectRatio - aspect ratio for image crop (e.g. 1.77(7) for 16:9) - */ - public void setTargetAspectRatio(float targetAspectRatio) { - mTargetAspectRatio = targetAspectRatio; - setupCropBounds(); - postInvalidate(); - } - - /** - * This method setups crop bounds rectangles for given aspect ratio and view size. - * {@link #mCropViewRect} is used to draw crop bounds - uses padding. - */ - public void setupCropBounds() { - int height = (int) (mThisWidth / mTargetAspectRatio); - if (height > mThisHeight) { - int width = (int) (mThisHeight * mTargetAspectRatio); - int halfDiff = (mThisWidth - width) / 2; - mCropViewRect.set(getPaddingLeft() + halfDiff, getPaddingTop(), - getPaddingLeft() + width + halfDiff, getPaddingTop() + mThisHeight); - } else { - int halfDiff = (mThisHeight - height) / 2; - mCropViewRect.set(getPaddingLeft(), getPaddingTop() + halfDiff, - getPaddingLeft() + mThisWidth, getPaddingTop() + height + halfDiff); - } - - if (mCallback != null) { - mCallback.onCropRectUpdated(mCropViewRect); - } - - updateGridPoints(); - } - - private void updateGridPoints() { - mCropGridCorners = RectUtils.getCornersFromRect(mCropViewRect); - - mGridPoints = null; - mCircularPath.reset(); - mCircularPath.addOval(mCropViewRect, Path.Direction.CW); - } - - protected void init() { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2 && - Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - setLayerType(LAYER_TYPE_SOFTWARE, null); - } - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - if (changed) { - left = getPaddingLeft(); - top = getPaddingTop(); - right = getWidth() - getPaddingRight(); - bottom = getHeight() - getPaddingBottom(); - mThisWidth = right - left; - mThisHeight = bottom - top; - } - } - - /** - * Along with image there are dimmed layer, crop bounds and crop guidelines that must be drawn. - */ - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - drawDimmedLayer(canvas); - drawCropGrid(canvas); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (mCropViewRect.isEmpty() || !mIsFreestyleCropEnabled) return false; - - float x = event.getX(); - float y = event.getY(); - - if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN) { - mCurrentTouchCornerIndex = getCurrentTouchCorner(x, y); - return mCurrentTouchCornerIndex != -1; - } - - if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_MOVE) { - if (event.getPointerCount() == 1 && mCurrentTouchCornerIndex != -1) { - - x = Math.min(Math.max(x, getPaddingLeft()), getWidth() - getPaddingRight()); - y = Math.min(Math.max(y, getPaddingTop()), getHeight() - getPaddingBottom()); - - resizeCropViewRect(x, y); - - return true; - } - } - - if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP) { - mCurrentTouchCornerIndex = -1; - if (mCallback != null) { - mCallback.onCropRectUpdated(mCropViewRect); - } - } - - return false; - } - - /** - * * The order of the corners is: - * 0------->1 - * ^ | - * | | - * | v - * 3<-------2 - */ - private void resizeCropViewRect(float touchX, float touchY) { - mTempRect.set(mCropViewRect); - - switch (mCurrentTouchCornerIndex) { - case 0: - mTempRect.set(touchX, touchY, mCropViewRect.right, mCropViewRect.bottom); - break; - case 1: - mTempRect.set(mCropViewRect.left, touchY, touchX, mCropViewRect.bottom); - break; - case 2: - mTempRect.set(mCropViewRect.left, mCropViewRect.top, touchX, touchY); - break; - case 3: - mTempRect.set(touchX, mCropViewRect.top, mCropViewRect.right, touchY); - break; - } - - boolean changeHeight = mTempRect.height() >= mCropRectMinSize; - boolean changeWidth = mTempRect.width() >= mCropRectMinSize; - mCropViewRect.set( - changeWidth ? mTempRect.left : mCropViewRect.left, - changeHeight ? mTempRect.top : mCropViewRect.top, - changeWidth ? mTempRect.right : mCropViewRect.right, - changeHeight ? mTempRect.bottom : mCropViewRect.bottom); - - if (changeHeight || changeWidth) { - updateGridPoints(); - postInvalidate(); - } - } - - /** - * * The order of the corners in the float array is: - * 0------->1 - * ^ | - * | | - * | v - * 3<-------2 - * - * @return - index of corner that is being dragged - */ - private int getCurrentTouchCorner(float touchX, float touchY) { - int closestPointIndex = -1; - double closestPointDistance = mTouchPointThreshold; - for (int i = 0; i < 8; i += 2) { - double distanceToCorner = Math.sqrt(Math.pow(touchX - mCropGridCorners[i], 2) - + Math.pow(touchY - mCropGridCorners[i + 1], 2)); - if (distanceToCorner < closestPointDistance) { - closestPointDistance = distanceToCorner; - closestPointIndex = i / 2; - } - } - return closestPointIndex; - } - - /** - * This method draws dimmed area around the crop bounds. - * - * @param canvas - valid canvas object - */ - protected void drawDimmedLayer(@NonNull Canvas canvas) { - canvas.save(); - if (mOvalDimmedLayer) { - canvas.clipPath(mCircularPath, Region.Op.DIFFERENCE); - } else { - canvas.clipRect(mCropViewRect, Region.Op.DIFFERENCE); - } - canvas.drawColor(mDimmedColor); - canvas.restore(); - - if (mOvalDimmedLayer) { // Draw 1px stroke to fix antialias - canvas.drawOval(mCropViewRect, mDimmedStrokePaint); - } - } - - /** - * This method draws crop bounds (empty rectangle) - * and crop guidelines (vertical and horizontal lines inside the crop bounds) if needed. - * - * @param canvas - valid canvas object - */ - protected void drawCropGrid(@NonNull Canvas canvas) { - if (mShowCropGrid) { - if (mGridPoints == null && !mCropViewRect.isEmpty()) { - - mGridPoints = new float[(mCropGridRowCount) * 4 + (mCropGridColumnCount) * 4]; - - int index = 0; - for (int i = 0; i < mCropGridRowCount; i++) { - mGridPoints[index++] = mCropViewRect.left; - mGridPoints[index++] = (mCropViewRect.height() * (((float) i + 1.0f) / (float) (mCropGridRowCount + 1))) + mCropViewRect.top; - mGridPoints[index++] = mCropViewRect.right; - mGridPoints[index++] = (mCropViewRect.height() * (((float) i + 1.0f) / (float) (mCropGridRowCount + 1))) + mCropViewRect.top; - } - - for (int i = 0; i < mCropGridColumnCount; i++) { - mGridPoints[index++] = (mCropViewRect.width() * (((float) i + 1.0f) / (float) (mCropGridColumnCount + 1))) + mCropViewRect.left; - mGridPoints[index++] = mCropViewRect.top; - mGridPoints[index++] = (mCropViewRect.width() * (((float) i + 1.0f) / (float) (mCropGridColumnCount + 1))) + mCropViewRect.left; - mGridPoints[index++] = mCropViewRect.bottom; - } - } - - if (mGridPoints != null) { - canvas.drawLines(mGridPoints, mCropGridPaint); - } - } - - if (mShowCropFrame) { - canvas.drawRect(mCropViewRect, mCropFramePaint); - } - - if (mIsFreestyleCropEnabled) { - canvas.save(); - - mTempRect.set(mCropViewRect); - mTempRect.inset(mCropRectCornerTouchAreaLineLength, -mCropRectCornerTouchAreaLineLength); - canvas.clipRect(mTempRect, Region.Op.DIFFERENCE); - - mTempRect.set(mCropViewRect); - mTempRect.inset(-mCropRectCornerTouchAreaLineLength, mCropRectCornerTouchAreaLineLength); - canvas.clipRect(mTempRect, Region.Op.DIFFERENCE); - - canvas.drawRect(mCropViewRect, mCropFrameCornersPaint); - - canvas.restore(); - } - } - - /** - * This method extracts all needed values from the styled attributes. - * Those are used to configure the view. - */ - @SuppressWarnings("deprecation") - protected void processStyledAttributes(@NonNull TypedArray a) { - mOvalDimmedLayer = a.getBoolean(R.styleable.gallery_ucrop_UCropView_gallery_ucrop_oval_dimmed_layer, DEFAULT_OVAL_DIMMED_LAYER); - mDimmedColor = a.getColor(R.styleable.gallery_ucrop_UCropView_gallery_ucrop_dimmed_color, - getResources().getColor(R.color.gallery_default_ucrop_color_default_dimmed)); - mDimmedStrokePaint.setColor(mDimmedColor); - mDimmedStrokePaint.setStyle(Paint.Style.STROKE); - mDimmedStrokePaint.setStrokeWidth(1); - - initCropFrameStyle(a); - mShowCropFrame = a.getBoolean(R.styleable.gallery_ucrop_UCropView_gallery_ucrop_show_frame, DEFAULT_SHOW_CROP_FRAME); - - initCropGridStyle(a); - mShowCropGrid = a.getBoolean(R.styleable.gallery_ucrop_UCropView_gallery_ucrop_show_grid, DEFAULT_SHOW_CROP_GRID); - } - - /** - * This method setups Paint object for the crop bounds. - */ - @SuppressWarnings("deprecation") - private void initCropFrameStyle(@NonNull TypedArray a) { - int cropFrameStrokeSize = a.getDimensionPixelSize(R.styleable.gallery_ucrop_UCropView_gallery_ucrop_frame_stroke_size, - getResources().getDimensionPixelSize(R.dimen.gallery_ucrop_default_crop_frame_stroke_width)); - int cropFrameColor = a.getColor(R.styleable.gallery_ucrop_UCropView_gallery_ucrop_frame_color, - getResources().getColor(R.color.gallery_default_ucrop_color_default_crop_frame)); - mCropFramePaint.setStrokeWidth(cropFrameStrokeSize); - mCropFramePaint.setColor(cropFrameColor); - mCropFramePaint.setStyle(Paint.Style.STROKE); - - mCropFrameCornersPaint.setStrokeWidth(cropFrameStrokeSize * 3); - mCropFrameCornersPaint.setColor(cropFrameColor); - mCropFrameCornersPaint.setStyle(Paint.Style.STROKE); - } - - /** - * This method setups Paint object for the crop guidelines. - */ - @SuppressWarnings("deprecation") - private void initCropGridStyle(@NonNull TypedArray a) { - int cropGridStrokeSize = a.getDimensionPixelSize(R.styleable.gallery_ucrop_UCropView_gallery_ucrop_grid_stroke_size, - getResources().getDimensionPixelSize(R.dimen.gallery_ucrop_default_crop_grid_stroke_width)); - int cropGridColor = a.getColor(R.styleable.gallery_ucrop_UCropView_gallery_ucrop_grid_color, - getResources().getColor(R.color.gallery_default_ucrop_color_default_crop_grid)); - mCropGridPaint.setStrokeWidth(cropGridStrokeSize); - mCropGridPaint.setColor(cropGridColor); - - mCropGridRowCount = a.getInt(R.styleable.gallery_ucrop_UCropView_gallery_ucrop_grid_row_count, DEFAULT_CROP_GRID_ROW_COUNT); - mCropGridColumnCount = a.getInt(R.styleable.gallery_ucrop_UCropView_gallery_ucrop_grid_column_count, DEFAULT_CROP_GRID_COLUMN_COUNT); - } - -} \ No newline at end of file diff --git a/library/src/main/java/com/yalantis/ucrop/view/TransformImageView.java b/library/src/main/java/com/yalantis/ucrop/view/TransformImageView.java deleted file mode 100755 index 869ea289..00000000 --- a/library/src/main/java/com/yalantis/ucrop/view/TransformImageView.java +++ /dev/null @@ -1,338 +0,0 @@ -package com.yalantis.ucrop.view; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Matrix; -import android.graphics.RectF; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.support.annotation.IntRange; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.util.AttributeSet; -import android.util.Log; -import android.widget.ImageView; - -import com.yalantis.ucrop.callback.BitmapLoadCallback; -import com.yalantis.ucrop.model.ExifInfo; -import com.yalantis.ucrop.util.BitmapLoadUtils; -import com.yalantis.ucrop.util.FastBitmapDrawable; -import com.yalantis.ucrop.util.RectUtils; - -/** - * Created by Oleksii Shliama (https://github.com/shliama). - *

- * This class provides base logic to setup the image, transform it with matrix (move, scale, rotate), - * and methods to get current matrix state. - */ -public class TransformImageView extends ImageView { - - private static final String TAG = "TransformImageView"; - - private static final int RECT_CORNER_POINTS_COORDS = 8; - private static final int RECT_CENTER_POINT_COORDS = 2; - private static final int MATRIX_VALUES_COUNT = 9; - - protected final float[] mCurrentImageCorners = new float[RECT_CORNER_POINTS_COORDS]; - protected final float[] mCurrentImageCenter = new float[RECT_CENTER_POINT_COORDS]; - - private final float[] mMatrixValues = new float[MATRIX_VALUES_COUNT]; - - protected Matrix mCurrentImageMatrix = new Matrix(); - protected int mThisWidth, mThisHeight; - - protected TransformImageListener mTransformImageListener; - - private float[] mInitialImageCorners; - private float[] mInitialImageCenter; - - protected boolean mBitmapDecoded = false; - protected boolean mBitmapLaidOut = false; - - private int mMaxBitmapSize = 0; - - private String mImageInputPath, mImageOutputPath; - private ExifInfo mExifInfo; - - /** - * Interface for rotation and scale change notifying. - */ - public interface TransformImageListener { - - void onLoadComplete(); - - void onLoadFailure(@NonNull Exception e); - - void onRotate(float currentAngle); - - void onScale(float currentScale); - - } - - public TransformImageView(Context context) { - this(context, null); - } - - public TransformImageView(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public TransformImageView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - init(); - } - - public void setTransformImageListener(TransformImageListener transformImageListener) { - mTransformImageListener = transformImageListener; - } - - @Override - public void setScaleType(ScaleType scaleType) { - if (scaleType == ScaleType.MATRIX) { - super.setScaleType(scaleType); - } else { - Log.w(TAG, "Invalid ScaleType. Only ScaleType.MATRIX can be used"); - } - } - - /** - * Setter for {@link #mMaxBitmapSize} value. - * Be sure to call it before {@link #setImageURI(Uri)} or other image setters. - * - * @param maxBitmapSize - max size for both width and height of bitmap that will be used in the view. - */ - public void setMaxBitmapSize(int maxBitmapSize) { - mMaxBitmapSize = maxBitmapSize; - } - - public int getMaxBitmapSize() { - if (mMaxBitmapSize <= 0) { - mMaxBitmapSize = BitmapLoadUtils.calculateMaxBitmapSize(getContext()); - } - return mMaxBitmapSize; - } - - @Override - public void setImageBitmap(final Bitmap bitmap) { - setImageDrawable(new FastBitmapDrawable(bitmap)); - } - - public String getImageInputPath() { - return mImageInputPath; - } - - public String getImageOutputPath() { - return mImageOutputPath; - } - - public ExifInfo getExifInfo() { - return mExifInfo; - } - - /** - * This method takes an Uri as a parameter, then calls method to decode it into Bitmap with specified size. - * - * @param imageUri - image Uri - * @throws Exception - can throw exception if having problems with decoding Uri or OOM. - */ - public void setImageUri(@NonNull Uri imageUri, @Nullable Uri outputUri) throws Exception { - int maxBitmapSize = getMaxBitmapSize(); - - BitmapLoadUtils.decodeBitmapInBackground(getContext(), imageUri, outputUri, maxBitmapSize, maxBitmapSize, - new BitmapLoadCallback() { - - @Override - public void onBitmapLoaded(@NonNull Bitmap bitmap, @NonNull ExifInfo exifInfo, @NonNull String imageInputPath, @Nullable String imageOutputPath) { - mImageInputPath = imageInputPath; - mImageOutputPath = imageOutputPath; - mExifInfo = exifInfo; - - mBitmapDecoded = true; - setImageBitmap(bitmap); - } - - @Override - public void onFailure(@NonNull Exception bitmapWorkerException) { - Log.e(TAG, "onFailure: setImageUri", bitmapWorkerException); - if (mTransformImageListener != null) { - mTransformImageListener.onLoadFailure(bitmapWorkerException); - } - } - }); - } - - /** - * @return - current image scale value. - * [1.0f - for original image, 2.0f - for 200% scaled image, etc.] - */ - public float getCurrentScale() { - return getMatrixScale(mCurrentImageMatrix); - } - - /** - * This method calculates scale value for given Matrix object. - */ - public float getMatrixScale(@NonNull Matrix matrix) { - return (float) Math.sqrt(Math.pow(getMatrixValue(matrix, Matrix.MSCALE_X), 2) - + Math.pow(getMatrixValue(matrix, Matrix.MSKEW_Y), 2)); - } - - /** - * @return - current image rotation angle. - */ - public float getCurrentAngle() { - return getMatrixAngle(mCurrentImageMatrix); - } - - /** - * This method calculates rotation angle for given Matrix object. - */ - public float getMatrixAngle(@NonNull Matrix matrix) { - return (float) -(Math.atan2(getMatrixValue(matrix, Matrix.MSKEW_X), - getMatrixValue(matrix, Matrix.MSCALE_X)) * (180 / Math.PI)); - } - - @Override - public void setImageMatrix(Matrix matrix) { - super.setImageMatrix(matrix); - updateCurrentImagePoints(); - } - - @Nullable - public Bitmap getViewBitmap() { - if (getDrawable() == null || !(getDrawable() instanceof FastBitmapDrawable)) { - return null; - } else { - return ((FastBitmapDrawable) getDrawable()).getBitmap(); - } - } - - /** - * This method translates current image. - * - * @param deltaX - horizontal shift - * @param deltaY - vertical shift - */ - public void postTranslate(float deltaX, float deltaY) { - if (deltaX != 0 || deltaY != 0) { - mCurrentImageMatrix.postTranslate(deltaX, deltaY); - setImageMatrix(mCurrentImageMatrix); - } - } - - /** - * This method scales current image. - * - * @param deltaScale - scale value - * @param px - scale center X - * @param py - scale center Y - */ - public void postScale(float deltaScale, float px, float py) { - if (deltaScale != 0) { - mCurrentImageMatrix.postScale(deltaScale, deltaScale, px, py); - setImageMatrix(mCurrentImageMatrix); - if (mTransformImageListener != null) { - mTransformImageListener.onScale(getMatrixScale(mCurrentImageMatrix)); - } - } - } - - /** - * This method rotates current image. - * - * @param deltaAngle - rotation angle - * @param px - rotation center X - * @param py - rotation center Y - */ - public void postRotate(float deltaAngle, float px, float py) { - if (deltaAngle != 0) { - mCurrentImageMatrix.postRotate(deltaAngle, px, py); - setImageMatrix(mCurrentImageMatrix); - if (mTransformImageListener != null) { - mTransformImageListener.onRotate(getMatrixAngle(mCurrentImageMatrix)); - } - } - } - - protected void init() { - setScaleType(ScaleType.MATRIX); - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - if (changed || (mBitmapDecoded && !mBitmapLaidOut)) { - - left = getPaddingLeft(); - top = getPaddingTop(); - right = getWidth() - getPaddingRight(); - bottom = getHeight() - getPaddingBottom(); - mThisWidth = right - left; - mThisHeight = bottom - top; - - onImageLaidOut(); - } - } - - /** - * When image is laid out {@link #mInitialImageCenter} and {@link #mInitialImageCenter} - * must be set. - */ - protected void onImageLaidOut() { - final Drawable drawable = getDrawable(); - if (drawable == null) { - return; - } - - float w = drawable.getIntrinsicWidth(); - float h = drawable.getIntrinsicHeight(); - - Log.d(TAG, String.format("Image size: [%d:%d]", (int) w, (int) h)); - - RectF initialImageRect = new RectF(0, 0, w, h); - mInitialImageCorners = RectUtils.getCornersFromRect(initialImageRect); - mInitialImageCenter = RectUtils.getCenterFromRect(initialImageRect); - - mBitmapLaidOut = true; - - if (mTransformImageListener != null) { - mTransformImageListener.onLoadComplete(); - } - } - - /** - * This method returns Matrix value for given index. - * - * @param matrix - valid Matrix object - * @param valueIndex - index of needed value. See {@link Matrix#MSCALE_X} and others. - * @return - matrix value for index - */ - protected float getMatrixValue(@NonNull Matrix matrix, @IntRange(from = 0, to = MATRIX_VALUES_COUNT) int valueIndex) { - matrix.getValues(mMatrixValues); - return mMatrixValues[valueIndex]; - } - - /** - * This method logs given matrix X, Y, scale, and angle values. - * Can be used for debug. - */ - @SuppressWarnings("unused") - protected void printMatrix(@NonNull String logPrefix, @NonNull Matrix matrix) { - float x = getMatrixValue(matrix, Matrix.MTRANS_X); - float y = getMatrixValue(matrix, Matrix.MTRANS_Y); - float rScale = getMatrixScale(matrix); - float rAngle = getMatrixAngle(matrix); - Log.d(TAG, logPrefix + ": matrix: { x: " + x + ", y: " + y + ", scale: " + rScale + ", angle: " + rAngle + " }"); - } - - /** - * This method updates current image corners and center points that are stored in - * {@link #mCurrentImageCorners} and {@link #mCurrentImageCenter} arrays. - * Those are used for several calculations. - */ - private void updateCurrentImagePoints() { - mCurrentImageMatrix.mapPoints(mCurrentImageCorners, mInitialImageCorners); - mCurrentImageMatrix.mapPoints(mCurrentImageCenter, mInitialImageCenter); - } - -} diff --git a/library/src/main/java/com/yalantis/ucrop/view/UCropView.java b/library/src/main/java/com/yalantis/ucrop/view/UCropView.java deleted file mode 100755 index 99447a03..00000000 --- a/library/src/main/java/com/yalantis/ucrop/view/UCropView.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.yalantis.ucrop.view; - -import android.content.Context; -import android.content.res.TypedArray; -import android.support.annotation.NonNull; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.widget.FrameLayout; - -import cn.finalteam.rxgalleryfinal.R; - -public class UCropView extends FrameLayout { - - private final GestureCropImageView mGestureCropImageView; - private final OverlayView mViewOverlay; - - public UCropView(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public UCropView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - - LayoutInflater.from(context).inflate(R.layout.gallery_ucrop_view, this, true); - mGestureCropImageView = (GestureCropImageView) findViewById(R.id.image_view_crop); - mViewOverlay = (OverlayView) findViewById(R.id.view_overlay); - - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.gallery_ucrop_UCropView); - mViewOverlay.processStyledAttributes(a); - mGestureCropImageView.processStyledAttributes(a); - a.recycle(); - - - mGestureCropImageView.setCropBoundsChangeListener(cropRatio -> mViewOverlay.setTargetAspectRatio(cropRatio)); - mViewOverlay.setOverlayViewChangeListener(cropRect -> mGestureCropImageView.setCropRect(cropRect)); - } - - @Override - public boolean shouldDelayChildPressedState() { - return false; - } - - @NonNull - public GestureCropImageView getCropImageView() { - return mGestureCropImageView; - } - - @NonNull - public OverlayView getOverlayView() { - return mViewOverlay; - } - -} \ No newline at end of file diff --git a/library/src/main/java/com/yalantis/ucrop/view/widget/AspectRatioTextView.java b/library/src/main/java/com/yalantis/ucrop/view/widget/AspectRatioTextView.java deleted file mode 100755 index 6720cd17..00000000 --- a/library/src/main/java/com/yalantis/ucrop/view/widget/AspectRatioTextView.java +++ /dev/null @@ -1,164 +0,0 @@ -package com.yalantis.ucrop.view.widget; - -import android.annotation.TargetApi; -import android.content.Context; -import android.content.res.ColorStateList; -import android.content.res.TypedArray; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Rect; -import android.os.Build; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.v4.content.ContextCompat; -import android.text.TextUtils; -import android.util.AttributeSet; -import android.view.Gravity; -import android.widget.TextView; - -import com.yalantis.ucrop.model.AspectRatio; -import com.yalantis.ucrop.view.CropImageView; - -import java.util.Locale; - -import cn.finalteam.rxgalleryfinal.R; - -/** - * Created by Oleksii Shliama (https://github.com/shliama). - */ -public class AspectRatioTextView extends TextView { - - private final Rect mCanvasClipBounds = new Rect(); - private Paint mDotPaint; - private int mDotSize; - private float mAspectRatio; - - private String mAspectRatioTitle; - private float mAspectRatioX, mAspectRatioY; - - public AspectRatioTextView(Context context) { - this(context, null); - } - - public AspectRatioTextView(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public AspectRatioTextView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.gallery_ucrop_AspectRatioTextView); - init(a); - } - - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - public AspectRatioTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.gallery_ucrop_AspectRatioTextView); - init(a); - } - - /** - * @param activeColor the resolved color for active elements - */ - - public void setActiveColor(@ColorInt int activeColor) { - applyActiveColor(activeColor); - invalidate(); - } - - public void setAspectRatio(@NonNull AspectRatio aspectRatio) { - mAspectRatioTitle = aspectRatio.getAspectRatioTitle(); - mAspectRatioX = aspectRatio.getAspectRatioX(); - mAspectRatioY = aspectRatio.getAspectRatioY(); - - if (mAspectRatioX == CropImageView.SOURCE_IMAGE_ASPECT_RATIO || mAspectRatioY == CropImageView.SOURCE_IMAGE_ASPECT_RATIO) { - mAspectRatio = CropImageView.SOURCE_IMAGE_ASPECT_RATIO; - } else { - mAspectRatio = mAspectRatioX / mAspectRatioY; - } - - setTitle(); - } - - public float getAspectRatio(boolean toggleRatio) { - if (toggleRatio) { - toggleAspectRatio(); - setTitle(); - } - return mAspectRatio; - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - - if (isSelected()) { - canvas.getClipBounds(mCanvasClipBounds); - canvas.drawCircle((mCanvasClipBounds.right - mCanvasClipBounds.left) / 2.0f, mCanvasClipBounds.bottom - mDotSize, - mDotSize / 2, mDotPaint); - } - } - - @SuppressWarnings("deprecation") - private void init(@NonNull TypedArray a) { - setGravity(Gravity.CENTER_HORIZONTAL); - - mAspectRatioTitle = a.getString(R.styleable.gallery_ucrop_AspectRatioTextView_gallery_ucrop_artv_ratio_title); - mAspectRatioX = a.getFloat(R.styleable.gallery_ucrop_AspectRatioTextView_gallery_ucrop_artv_ratio_x, CropImageView.SOURCE_IMAGE_ASPECT_RATIO); - mAspectRatioY = a.getFloat(R.styleable.gallery_ucrop_AspectRatioTextView_gallery_ucrop_artv_ratio_y, CropImageView.SOURCE_IMAGE_ASPECT_RATIO); - - if (mAspectRatioX == CropImageView.SOURCE_IMAGE_ASPECT_RATIO || mAspectRatioY == CropImageView.SOURCE_IMAGE_ASPECT_RATIO) { - mAspectRatio = CropImageView.SOURCE_IMAGE_ASPECT_RATIO; - } else { - mAspectRatio = mAspectRatioX / mAspectRatioY; - } - - mDotSize = getContext().getResources().getDimensionPixelSize(R.dimen.gallery_ucrop_size_dot_scale_text_view); - mDotPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mDotPaint.setStyle(Paint.Style.FILL); - - setTitle(); - - int activeColor = getResources().getColor(R.color.gallery_default_ucrop_color_widget_active); - applyActiveColor(activeColor); - - a.recycle(); - } - - private void applyActiveColor(@ColorInt int activeColor) { - if (mDotPaint != null) { - mDotPaint.setColor(activeColor); - } - ColorStateList textViewColorStateList = new ColorStateList( - new int[][]{ - new int[]{android.R.attr.state_selected}, - new int[]{0} - }, - new int[]{ - activeColor, - ContextCompat.getColor(getContext(), R.color.gallery_default_ucrop_color_widget) - } - ); - - setTextColor(textViewColorStateList); - } - - private void toggleAspectRatio() { - if (mAspectRatio != CropImageView.SOURCE_IMAGE_ASPECT_RATIO) { - float tempRatioW = mAspectRatioX; - mAspectRatioX = mAspectRatioY; - mAspectRatioY = tempRatioW; - - mAspectRatio = mAspectRatioX / mAspectRatioY; - } - } - - private void setTitle() { - if (!TextUtils.isEmpty(mAspectRatioTitle)) { - setText(mAspectRatioTitle); - } else { - setText(String.format(Locale.US, "%d:%d", (int) mAspectRatioX, (int) mAspectRatioY)); - } - } - -} diff --git a/library/src/main/java/com/yalantis/ucrop/view/widget/HorizontalProgressWheelView.java b/library/src/main/java/com/yalantis/ucrop/view/widget/HorizontalProgressWheelView.java deleted file mode 100755 index cdf8affc..00000000 --- a/library/src/main/java/com/yalantis/ucrop/view/widget/HorizontalProgressWheelView.java +++ /dev/null @@ -1,152 +0,0 @@ -package com.yalantis.ucrop.view.widget; - -import android.annotation.TargetApi; -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Rect; -import android.os.Build; -import android.support.annotation.ColorInt; -import android.support.v4.content.ContextCompat; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; - -import cn.finalteam.rxgalleryfinal.R; - - -/** - * Created by Oleksii Shliama (https://github.com/shliama). - */ -public class HorizontalProgressWheelView extends View { - - private final Rect mCanvasClipBounds = new Rect(); - - private ScrollingListener mScrollingListener; - private float mLastTouchedPosition; - - private Paint mProgressLinePaint; - private int mProgressLineWidth, mProgressLineHeight; - private int mProgressLineMargin; - - private boolean mScrollStarted; - private float mTotalScrollDistance; - - private int mMiddleLineColor; - - public HorizontalProgressWheelView(Context context) { - this(context, null); - } - - public HorizontalProgressWheelView(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public HorizontalProgressWheelView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(); - } - - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - public HorizontalProgressWheelView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - } - - public void setScrollingListener(ScrollingListener scrollingListener) { - mScrollingListener = scrollingListener; - } - - public void setMiddleLineColor(@ColorInt int middleLineColor) { - mMiddleLineColor = middleLineColor; - invalidate(); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - mLastTouchedPosition = event.getX(); - break; - case MotionEvent.ACTION_UP: - if (mScrollingListener != null) { - mScrollStarted = false; - mScrollingListener.onScrollEnd(); - } - break; - case MotionEvent.ACTION_MOVE: - float distance = event.getX() - mLastTouchedPosition; - if (distance != 0) { - if (!mScrollStarted) { - mScrollStarted = true; - if (mScrollingListener != null) { - mScrollingListener.onScrollStart(); - } - } - onScrollEvent(event, distance); - } - break; - } - return true; - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - canvas.getClipBounds(mCanvasClipBounds); - - int linesCount = mCanvasClipBounds.width() / (mProgressLineWidth + mProgressLineMargin); - float deltaX = (mTotalScrollDistance) % (float) (mProgressLineMargin + mProgressLineWidth); - - mProgressLinePaint.setColor(getResources().getColor(R.color.gallery_default_ucrop_color_progress_wheel_line)); - for (int i = 0; i < linesCount; i++) { - if (i < (linesCount / 4)) { - mProgressLinePaint.setAlpha((int) (255 * (i / (float) (linesCount / 4)))); - } else if (i > (linesCount * 3 / 4)) { - mProgressLinePaint.setAlpha((int) (255 * ((linesCount - i) / (float) (linesCount / 4)))); - } else { - mProgressLinePaint.setAlpha(255); - } - canvas.drawLine( - -deltaX + mCanvasClipBounds.left + i * (mProgressLineWidth + mProgressLineMargin), - mCanvasClipBounds.centerY() - mProgressLineHeight / 4.0f, - -deltaX + mCanvasClipBounds.left + i * (mProgressLineWidth + mProgressLineMargin), - mCanvasClipBounds.centerY() + mProgressLineHeight / 4.0f, mProgressLinePaint); - } - - mProgressLinePaint.setColor(mMiddleLineColor); - canvas.drawLine(mCanvasClipBounds.centerX(), mCanvasClipBounds.centerY() - mProgressLineHeight / 2.0f, mCanvasClipBounds.centerX(), mCanvasClipBounds.centerY() + mProgressLineHeight / 2.0f, mProgressLinePaint); - - } - - private void onScrollEvent(MotionEvent event, float distance) { - mTotalScrollDistance -= distance; - postInvalidate(); - mLastTouchedPosition = event.getX(); - if (mScrollingListener != null) { - mScrollingListener.onScroll(-distance, mTotalScrollDistance); - } - } - - private void init() { - mMiddleLineColor = ContextCompat.getColor(getContext(), R.color.gallery_default_ucrop_color_progress_wheel_line); - - mProgressLineWidth = getContext().getResources().getDimensionPixelSize(R.dimen.gallery_ucrop_width_horizontal_wheel_progress_line); - mProgressLineHeight = getContext().getResources().getDimensionPixelSize(R.dimen.gallery_ucrop_height_horizontal_wheel_progress_line); - mProgressLineMargin = getContext().getResources().getDimensionPixelSize(R.dimen.gallery_ucrop_margin_horizontal_wheel_progress_line); - - mProgressLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mProgressLinePaint.setStyle(Paint.Style.STROKE); - mProgressLinePaint.setStrokeWidth(mProgressLineWidth); - - } - - public interface ScrollingListener { - - void onScrollStart(); - - void onScroll(float delta, float totalDistance); - - void onScrollEnd(); - } - -} diff --git a/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/MainActivity.java b/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/MainActivity.java index f8436be4..dc732d48 100644 --- a/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/MainActivity.java +++ b/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/MainActivity.java @@ -41,7 +41,7 @@ protected void onCreate(Bundle savedInstanceState) { .image() .radio() .crop() - .openCameraOnStart() + //.openCameraOnStart() .setTitle("标题你设置") .returnAfterShot() .imageLoader(ImageLoaderType.GLIDE) From 4204aeb682fa18ea7c8936d16f66db3a075dd7ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=85=8B=E4=BB=98?= Date: Wed, 25 Oct 2017 17:55:24 +0800 Subject: [PATCH 11/85] update --- library/build.gradle | 18 +- .../rxgalleryfinal/Configuration.java | 37 +- .../rxgalleryfinal/RxGalleryFinal.java | 134 ++-- .../rxgalleryfinal/RxGalleryFinalApi.java | 579 +++++++++++++++++ .../imageloader/AbsImageLoader.java | 16 +- .../imageloader/FrescoImageLoader.java | 51 +- .../imageloader/GlideImageLoader.java | 61 +- .../imageloader/ImageLoaderType.java | 4 +- .../imageloader/PicassoImageLoader.java | 17 +- .../imageloader/UniversalImageLoader.java | 28 +- .../MediaBucketFactoryInteractor.java | 6 +- .../interactor/MediaSrcFactoryInteractor.java | 13 +- .../MediaBucketFactoryInteractorImpl.java | 54 +- .../impl/MediaSrcFactoryInteractorImpl.java | 57 +- .../finalteam/rxgalleryfinal/rxbus/RxBus.java | 59 +- ...usSubscriber.java => RxBusDisposable.java} | 12 +- ...criber.java => RxBusResultDisposable.java} | 4 +- ...questStorageReadAccessPermissionEvent.java | 15 +- .../finalteam/rxgalleryfinal/rxjob/Job.java | 24 +- .../rxgalleryfinal/rxjob/JobCreator.java | 2 +- .../rxgalleryfinal/rxjob/JobManager.java | 81 ++- .../finalteam/rxgalleryfinal/rxjob/RxJob.java | 8 +- .../rxjob/job/ImageThmbnailJob.java | 10 +- .../rxjob/job/ImageThmbnailJobCreate.java | 10 +- .../rxgalleryfinal/ui/RxGalleryListener.java | 36 ++ .../ui/activity/MediaActivity.java | 121 ++-- .../ui/adapter/BucketAdapter.java | 65 +- .../ui/adapter/MediaGridAdapter.java | 196 ++++-- .../ui/adapter/MediaPreviewAdapter.java | 48 +- .../ui/base/IMultiImageCheckedListener.java | 11 + .../ui/base/IRadioImageCheckedListener.java | 18 + .../ui/fragment/MediaGridFragment.java | 611 ++++++++++++++---- .../ui/fragment/MediaPageFragment.java | 60 +- .../ui/fragment/MediaPreviewFragment.java | 45 +- .../rxgalleryfinal/utils/FileUtils.java | 9 +- .../rxgalleryfinal/utils/MediaUtils.java | 193 +++--- .../rxgalleryfinal/utils/ModelUtils.java | 32 + .../utils/PermissionCheckUtils.java | 37 +- .../rxgalleryfinal/utils/SimpleDateUtils.java | 17 + .../anim/gallery_ucrop_loader_circle_path.xml | 20 - .../gallery_ucrop_loader_circle_scale.xml | 28 - .../drawable-hdpi/gallery_ucrop_ic_angle.png | Bin 1080 -> 0 bytes .../drawable-hdpi/gallery_ucrop_ic_crop.png | Bin 414 -> 0 bytes .../drawable-hdpi/gallery_ucrop_ic_cross.png | Bin 433 -> 0 bytes .../drawable-hdpi/gallery_ucrop_ic_done.png | Bin 220 -> 0 bytes .../drawable-hdpi/gallery_ucrop_ic_next.png | Bin 461 -> 0 bytes .../drawable-hdpi/gallery_ucrop_ic_reset.png | Bin 980 -> 0 bytes .../drawable-hdpi/gallery_ucrop_ic_rotate.png | Bin 770 -> 0 bytes .../drawable-hdpi/gallery_ucrop_ic_scale.png | Bin 265 -> 0 bytes .../drawable-ldpi/gallery_ucrop_ic_angle.png | Bin 466 -> 0 bytes .../drawable-ldpi/gallery_ucrop_ic_crop.png | Bin 305 -> 0 bytes .../drawable-ldpi/gallery_ucrop_ic_cross.png | Bin 235 -> 0 bytes .../drawable-ldpi/gallery_ucrop_ic_done.png | Bin 151 -> 0 bytes .../drawable-ldpi/gallery_ucrop_ic_next.png | Bin 244 -> 0 bytes .../drawable-ldpi/gallery_ucrop_ic_reset.png | Bin 455 -> 0 bytes .../drawable-ldpi/gallery_ucrop_ic_rotate.png | Bin 380 -> 0 bytes .../drawable-ldpi/gallery_ucrop_ic_scale.png | Bin 256 -> 0 bytes .../drawable-mdpi/gallery_ucrop_ic_angle.png | Bin 657 -> 0 bytes .../drawable-mdpi/gallery_ucrop_ic_crop.png | Bin 325 -> 0 bytes .../drawable-mdpi/gallery_ucrop_ic_cross.png | Bin 301 -> 0 bytes .../drawable-mdpi/gallery_ucrop_ic_done.png | Bin 161 -> 0 bytes .../drawable-mdpi/gallery_ucrop_ic_next.png | Bin 303 -> 0 bytes .../drawable-mdpi/gallery_ucrop_ic_reset.png | Bin 556 -> 0 bytes .../drawable-mdpi/gallery_ucrop_ic_rotate.png | Bin 506 -> 0 bytes .../drawable-mdpi/gallery_ucrop_ic_scale.png | Bin 197 -> 0 bytes .../drawable-xhdpi/gallery_ucrop_ic_angle.png | Bin 1432 -> 0 bytes .../drawable-xhdpi/gallery_ucrop_ic_crop.png | Bin 601 -> 0 bytes .../drawable-xhdpi/gallery_ucrop_ic_cross.png | Bin 555 -> 0 bytes .../drawable-xhdpi/gallery_ucrop_ic_done.png | Bin 236 -> 0 bytes .../drawable-xhdpi/gallery_ucrop_ic_next.png | Bin 555 -> 0 bytes .../drawable-xhdpi/gallery_ucrop_ic_reset.png | Bin 1295 -> 0 bytes .../gallery_ucrop_ic_rotate.png | Bin 1011 -> 0 bytes .../drawable-xhdpi/gallery_ucrop_ic_scale.png | Bin 267 -> 0 bytes .../gallery_ucrop_ic_angle.png | Bin 2243 -> 0 bytes .../drawable-xxhdpi/gallery_ucrop_ic_crop.png | Bin 827 -> 0 bytes .../gallery_ucrop_ic_cross.png | Bin 811 -> 0 bytes .../drawable-xxhdpi/gallery_ucrop_ic_done.png | Bin 394 -> 0 bytes .../drawable-xxhdpi/gallery_ucrop_ic_next.png | Bin 840 -> 0 bytes .../gallery_ucrop_ic_reset.png | Bin 2095 -> 0 bytes .../gallery_ucrop_ic_rotate.png | Bin 1544 -> 0 bytes .../gallery_ucrop_ic_scale.png | Bin 352 -> 0 bytes .../gallery_ic_corner_selector.xml | 6 +- .../gallery_ucrop_ic_angle.png | Bin 3179 -> 0 bytes .../gallery_ucrop_ic_crop.png | Bin 1175 -> 0 bytes .../gallery_ucrop_ic_cross.png | Bin 1042 -> 0 bytes .../gallery_ucrop_ic_done.png | Bin 479 -> 0 bytes .../gallery_ucrop_ic_next.png | Bin 1065 -> 0 bytes .../gallery_ucrop_ic_reset.png | Bin 3029 -> 0 bytes .../gallery_ucrop_ic_rotate.png | Bin 2110 -> 0 bytes .../gallery_ucrop_ic_scale.png | Bin 443 -> 0 bytes .../drawable/gallery_bucket_item_selector.xml | 4 +- .../res/drawable/gallery_button_selector.xml | 22 +- .../res/drawable/gallery_default_image.xml | 5 +- .../drawable/gallery_ucrop_shadow_upside.xml | 7 - .../drawable/gallery_ucrop_vector_ic_crop.xml | 9 - .../drawable/gallery_ucrop_vector_loader.xml | 24 - .../gallery_ucrop_vector_loader_animated.xml | 11 - .../res/layout/gallery_activity_media.xml | 8 +- .../layout/gallery_adapter_bucket_item.xml | 23 +- .../layout/gallery_fragment_media_grid.xml | 50 +- .../layout/gallery_fragment_media_page.xml | 4 +- .../layout/gallery_fragment_media_preview.xml | 6 +- ...lery_loading_view_final_footer_default.xml | 12 +- .../gallery_media_image_preview_item.xml | 2 +- .../gallery_ucrop_activity_photobox.xml | 51 -- .../res/layout/gallery_ucrop_aspect_ratio.xml | 7 - .../res/layout/gallery_ucrop_controls.xml | 78 --- .../gallery_ucrop_layout_rotate_wheel.xml | 49 -- .../gallery_ucrop_layout_scale_wheel.xml | 20 - .../main/res/layout/gallery_ucrop_view.xml | 21 - .../res/layout/item_gallery_media_grid.xml | 42 ++ .../layout/item_gallery_media_grid_fresco.xml | 44 ++ .../res/menu/gallery_ucrop_menu_activity.xml | 18 - .../main/res/values-en/gallery_strings.xml | 3 + .../res/values-en/gallery_ucrop_strings.xml | 10 - library/src/main/res/values/gallery_attrs.xml | 87 +-- .../main/res/values/gallery_default_theme.xml | 13 +- .../src/main/res/values/gallery_strings.xml | 3 + .../main/res/values/gallery_ucrop_attrs.xml | 35 - .../main/res/values/gallery_ucrop_dimens.xml | 25 - .../main/res/values/gallery_ucrop_public.xml | 5 - .../main/res/values/gallery_ucrop_strings.xml | 10 - .../main/res/values/gallery_ucrop_styles.xml | 44 -- .../main/res/values/gallery_ucrop_values.xml | 4 - .../rxgalleryfinal/sample/MainActivity.java | 494 ++++++++++++-- .../sample/SimpleRxGalleryFinal.java | 157 +++++ .../imageloader/ImageLoaderActivity.java | 86 +++ sample/src/main/res/AndroidManifest.xml | 37 ++ .../main/res/layout/activity_imageloader.xml | 44 ++ sample/src/main/res/layout/activity_main.xml | 153 ++++- sample/src/main/res/values/themes.xml | 40 +- 131 files changed, 3183 insertions(+), 1437 deletions(-) create mode 100644 library/src/main/java/cn/finalteam/rxgalleryfinal/RxGalleryFinalApi.java rename library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/{RxBusSubscriber.java => RxBusDisposable.java} (69%) rename library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/{RxBusResultSubscriber.java => RxBusResultDisposable.java} (54%) create mode 100644 library/src/main/java/cn/finalteam/rxgalleryfinal/ui/RxGalleryListener.java create mode 100644 library/src/main/java/cn/finalteam/rxgalleryfinal/ui/base/IMultiImageCheckedListener.java create mode 100644 library/src/main/java/cn/finalteam/rxgalleryfinal/ui/base/IRadioImageCheckedListener.java create mode 100644 library/src/main/java/cn/finalteam/rxgalleryfinal/utils/ModelUtils.java create mode 100644 library/src/main/java/cn/finalteam/rxgalleryfinal/utils/SimpleDateUtils.java delete mode 100755 library/src/main/res/anim/gallery_ucrop_loader_circle_path.xml delete mode 100755 library/src/main/res/anim/gallery_ucrop_loader_circle_scale.xml delete mode 100755 library/src/main/res/drawable-hdpi/gallery_ucrop_ic_angle.png delete mode 100755 library/src/main/res/drawable-hdpi/gallery_ucrop_ic_crop.png delete mode 100755 library/src/main/res/drawable-hdpi/gallery_ucrop_ic_cross.png delete mode 100755 library/src/main/res/drawable-hdpi/gallery_ucrop_ic_done.png delete mode 100755 library/src/main/res/drawable-hdpi/gallery_ucrop_ic_next.png delete mode 100755 library/src/main/res/drawable-hdpi/gallery_ucrop_ic_reset.png delete mode 100755 library/src/main/res/drawable-hdpi/gallery_ucrop_ic_rotate.png delete mode 100755 library/src/main/res/drawable-hdpi/gallery_ucrop_ic_scale.png delete mode 100755 library/src/main/res/drawable-ldpi/gallery_ucrop_ic_angle.png delete mode 100755 library/src/main/res/drawable-ldpi/gallery_ucrop_ic_crop.png delete mode 100755 library/src/main/res/drawable-ldpi/gallery_ucrop_ic_cross.png delete mode 100755 library/src/main/res/drawable-ldpi/gallery_ucrop_ic_done.png delete mode 100755 library/src/main/res/drawable-ldpi/gallery_ucrop_ic_next.png delete mode 100755 library/src/main/res/drawable-ldpi/gallery_ucrop_ic_reset.png delete mode 100755 library/src/main/res/drawable-ldpi/gallery_ucrop_ic_rotate.png delete mode 100755 library/src/main/res/drawable-ldpi/gallery_ucrop_ic_scale.png delete mode 100755 library/src/main/res/drawable-mdpi/gallery_ucrop_ic_angle.png delete mode 100755 library/src/main/res/drawable-mdpi/gallery_ucrop_ic_crop.png delete mode 100755 library/src/main/res/drawable-mdpi/gallery_ucrop_ic_cross.png delete mode 100755 library/src/main/res/drawable-mdpi/gallery_ucrop_ic_done.png delete mode 100755 library/src/main/res/drawable-mdpi/gallery_ucrop_ic_next.png delete mode 100755 library/src/main/res/drawable-mdpi/gallery_ucrop_ic_reset.png delete mode 100755 library/src/main/res/drawable-mdpi/gallery_ucrop_ic_rotate.png delete mode 100755 library/src/main/res/drawable-mdpi/gallery_ucrop_ic_scale.png delete mode 100755 library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_angle.png delete mode 100755 library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_crop.png delete mode 100755 library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_cross.png delete mode 100755 library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_done.png delete mode 100755 library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_next.png delete mode 100755 library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_reset.png delete mode 100755 library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_rotate.png delete mode 100755 library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_scale.png delete mode 100755 library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_angle.png delete mode 100755 library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_crop.png delete mode 100755 library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_cross.png delete mode 100755 library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_done.png delete mode 100755 library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_next.png delete mode 100755 library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_reset.png delete mode 100755 library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_rotate.png delete mode 100755 library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_scale.png delete mode 100755 library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_angle.png delete mode 100755 library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_crop.png delete mode 100755 library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_cross.png delete mode 100755 library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_done.png delete mode 100755 library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_next.png delete mode 100755 library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_reset.png delete mode 100755 library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_rotate.png delete mode 100755 library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_scale.png delete mode 100755 library/src/main/res/drawable/gallery_ucrop_shadow_upside.xml delete mode 100755 library/src/main/res/drawable/gallery_ucrop_vector_ic_crop.xml delete mode 100755 library/src/main/res/drawable/gallery_ucrop_vector_loader.xml delete mode 100755 library/src/main/res/drawable/gallery_ucrop_vector_loader_animated.xml delete mode 100755 library/src/main/res/layout/gallery_ucrop_activity_photobox.xml delete mode 100755 library/src/main/res/layout/gallery_ucrop_aspect_ratio.xml delete mode 100755 library/src/main/res/layout/gallery_ucrop_controls.xml delete mode 100755 library/src/main/res/layout/gallery_ucrop_layout_rotate_wheel.xml delete mode 100755 library/src/main/res/layout/gallery_ucrop_layout_scale_wheel.xml delete mode 100755 library/src/main/res/layout/gallery_ucrop_view.xml create mode 100644 library/src/main/res/layout/item_gallery_media_grid.xml create mode 100644 library/src/main/res/layout/item_gallery_media_grid_fresco.xml delete mode 100755 library/src/main/res/menu/gallery_ucrop_menu_activity.xml delete mode 100644 library/src/main/res/values-en/gallery_ucrop_strings.xml delete mode 100755 library/src/main/res/values/gallery_ucrop_attrs.xml delete mode 100755 library/src/main/res/values/gallery_ucrop_dimens.xml delete mode 100755 library/src/main/res/values/gallery_ucrop_public.xml delete mode 100755 library/src/main/res/values/gallery_ucrop_strings.xml delete mode 100755 library/src/main/res/values/gallery_ucrop_styles.xml delete mode 100755 library/src/main/res/values/gallery_ucrop_values.xml create mode 100644 sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/SimpleRxGalleryFinal.java create mode 100644 sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/imageloader/ImageLoaderActivity.java create mode 100644 sample/src/main/res/AndroidManifest.xml create mode 100644 sample/src/main/res/layout/activity_imageloader.xml diff --git a/library/build.gradle b/library/build.gradle index ab9aa375..247f8cf2 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -6,12 +6,12 @@ apply plugin: "com.jfrog.bintray" android { - compileSdkVersion 24 - buildToolsVersion '24.0.1' + compileSdkVersion 25 + buildToolsVersion '25.0.3' defaultConfig { minSdkVersion 14 - targetSdkVersion 24 + targetSdkVersion 25 versionCode 3 versionName version @@ -38,14 +38,16 @@ android { dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') testCompile 'junit:junit:4.12' - compile 'io.reactivex:rxandroid:1.2.1' - compile 'io.reactivex:rxjava:1.1.9' - compile 'com.android.support:recyclerview-v7:24.2.0' - compile 'com.android.support:appcompat-v7:24.2.0' + compile 'io.reactivex.rxjava2:rxandroid:2.0.1' + compile 'io.reactivex.rxjava2:rxjava:2.1.0' + compile 'com.android.support:recyclerview-v7:25.3.1' + compile 'com.android.support:appcompat-v7:25.3.1' + compile "com.android.support:exifinterface:25.3.1" compile 'com.yalantis:ucrop:2.2.0' provided 'com.squareup.picasso:picasso:2.5.2' - provided 'com.facebook.fresco:fresco:0.12.0' + provided 'com.facebook.fresco:fresco:1.3.0' + provided 'com.facebook.fresco:animated-gif:1.3.0' provided 'com.github.bumptech.glide:glide:3.7.0' provided 'com.nostra13.universalimageloader:universal-image-loader:1.9.5' } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/Configuration.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/Configuration.java index d896a6f6..cae46f63 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/Configuration.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/Configuration.java @@ -66,7 +66,9 @@ protected Configuration() { private boolean ovalDimmedLayer = OverlayView.DEFAULT_CIRCLE_DIMMED_LAYER; private int maxResultWidth; private int maxResultHeight; - + private boolean isPlayGif; + private boolean hidePreview; + private boolean isVideoPreview; //==========UCrop END========== //设置显示标题 private String title = null; @@ -95,6 +97,9 @@ protected Configuration(Parcel in) { openCameraOnStart = in.readByte() != 0; title = in.readString(); returnAfterShot = in.readByte() != 0; + isPlayGif = in.readByte() != 0; + hidePreview = in.readByte() != 0; + isVideoPreview = in.readByte() != 0; } public static final Creator CREATOR = new Creator() { @@ -173,6 +178,30 @@ public void setReturnAfterShot(boolean returnAfterShot) { this.returnAfterShot = returnAfterShot; } + public boolean isHidePreview() { + return hidePreview; + } + + public void setHidePreview(boolean hidePreview) { + this.hidePreview = hidePreview; + } + + public boolean isPlayGif() { + return isPlayGif; + } + + public void setPlayGif(boolean playGif) { + isPlayGif = playGif; + } + + + public boolean isVideoPreview() { + return isVideoPreview; + } + + public void setVideoPreview(boolean videoPreview) { + isVideoPreview = videoPreview; + } public AbsImageLoader getImageLoader() { AbsImageLoader imageLoader = null; switch (imageLoaderType){ @@ -371,4 +400,10 @@ public void writeToParcel(Parcel parcel, int i) { parcel.writeString(title); parcel.writeByte((byte) (returnAfterShot ? 1 : 0)); } + + //#ADD + public int getImageLoaderType() { + return imageLoaderType; + } + } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/RxGalleryFinal.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/RxGalleryFinal.java index f0c1991b..8275703c 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/RxGalleryFinal.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/RxGalleryFinal.java @@ -15,37 +15,38 @@ import java.util.List; import cn.finalteam.rxgalleryfinal.bean.MediaBean; -import cn.finalteam.rxgalleryfinal.exception.UnknownImageLoaderTypeException; import cn.finalteam.rxgalleryfinal.imageloader.ImageLoaderType; import cn.finalteam.rxgalleryfinal.rxbus.RxBus; -import cn.finalteam.rxgalleryfinal.rxbus.RxBusResultSubscriber; +import cn.finalteam.rxgalleryfinal.rxbus.RxBusResultDisposable; import cn.finalteam.rxgalleryfinal.rxbus.event.BaseResultEvent; import cn.finalteam.rxgalleryfinal.rxbus.event.ImageMultipleResultEvent; import cn.finalteam.rxgalleryfinal.rxbus.event.ImageRadioResultEvent; import cn.finalteam.rxgalleryfinal.ui.activity.MediaActivity; +import cn.finalteam.rxgalleryfinal.utils.Logger; +import cn.finalteam.rxgalleryfinal.utils.ModelUtils; import cn.finalteam.rxgalleryfinal.utils.StorageUtils; -import rx.Subscription; +import io.reactivex.disposables.Disposable; /** - * Desction: - * Author:pengjianbo - * Date:16/5/7 下午4:20 + * Desction: RxGalleryFinal + * author: pengjianbo Dujinyang + * author: karl-dujinyang */ public class RxGalleryFinal { - private RxGalleryFinal(){} + private Configuration configuration = new Configuration(); + private RxBusResultDisposable isRadioDisposable; - Configuration configuration = new Configuration(); - static RxGalleryFinal instance; - RxBusResultSubscriber rxBusResultSubscriber; + private RxGalleryFinal() { + } public static RxGalleryFinal with(@NonNull Context context) { - instance = new RxGalleryFinal(); - instance.configuration.setContext(context); + RxGalleryFinal instance = new RxGalleryFinal(); + instance.configuration.setContext(context.getApplicationContext()); return instance; } - public RxGalleryFinal image(){ + public RxGalleryFinal image() { configuration.setImage(true); return this; } @@ -60,7 +61,27 @@ public RxGalleryFinal video() { // return this; // } - public RxGalleryFinal radio(){ + public RxGalleryFinal gif() { + configuration.setPlayGif(true); + return this; + } + + public RxGalleryFinal hidePreview() { + configuration.setHidePreview(true); + return this; + } + + public RxGalleryFinal videoPreview() { + configuration.setVideoPreview(true); + return this; + } + + public RxGalleryFinal gif(boolean flag) { + configuration.setPlayGif(flag); + return this; + } + + public RxGalleryFinal radio() { configuration.setRadio(true); return this; } @@ -70,12 +91,17 @@ public RxGalleryFinal multiple() { return this; } - public RxGalleryFinal crop(){ + public RxGalleryFinal crop() { configuration.setCrop(true); return this; } - public RxGalleryFinal maxSize(@IntRange(from = 1) int maxSize){ + public RxGalleryFinal crop(boolean flag) { + configuration.setCrop(flag); + return this; + } + + public RxGalleryFinal maxSize(@IntRange(from = 1) int maxSize) { configuration.setMaxSize(maxSize); return this; } @@ -87,7 +113,7 @@ public RxGalleryFinal selected(@NonNull List list) { public RxGalleryFinal imageConfig(@NonNull Bitmap.Config config) { int c = 3; - switch (config){ + switch (config) { case ALPHA_8: c = 1; break; @@ -101,21 +127,19 @@ public RxGalleryFinal imageConfig(@NonNull Bitmap.Config config) { c = 4; break; } - configuration.setImageConfig(c); - return this; } public RxGalleryFinal imageLoader(@NonNull ImageLoaderType imageLoaderType) { int type = 0; - if(imageLoaderType == ImageLoaderType.PICASSO){ + if (imageLoaderType == ImageLoaderType.PICASSO) { type = 1; - } else if(imageLoaderType == ImageLoaderType.GLIDE){ + } else if (imageLoaderType == ImageLoaderType.GLIDE) { type = 2; - } else if(imageLoaderType == ImageLoaderType.FRESCO){ + } else if (imageLoaderType == ImageLoaderType.FRESCO) { type = 3; - } else if(imageLoaderType == ImageLoaderType.UNIVERSAL){ + } else if (imageLoaderType == ImageLoaderType.UNIVERSAL) { type = 4; } configuration.setImageLoaderType(type); @@ -124,7 +148,6 @@ public RxGalleryFinal imageLoader(@NonNull ImageLoaderType imageLoaderType) { /** * 隐藏相机 - * @return */ public RxGalleryFinal hideCamera() { configuration.setHideCamera(true); @@ -150,8 +173,6 @@ public RxGalleryFinal returnAfterShot() { } /** * set to true to hide the bottom controls (shown by default) - * @param hide - * @return */ public RxGalleryFinal cropHideBottomControls(boolean hide) { configuration.setHideBottomControls(hide); @@ -160,7 +181,6 @@ public RxGalleryFinal cropHideBottomControls(boolean hide) { /** * Set compression quality [0-100] that will be used to save resulting Bitmap. - * @param compressQuality */ public RxGalleryFinal cropropCompressionQuality(@IntRange(from = 0) int compressQuality) { configuration.setCompressionQuality(compressQuality); @@ -169,13 +189,10 @@ public RxGalleryFinal cropropCompressionQuality(@IntRange(from = 0) int compress /** * Choose what set of gestures will be enabled on each tab - if any. - * @param tabScale - * @param tabRotate - * @param tabAspectRatio */ public RxGalleryFinal cropAllowedGestures(@UCropActivity.GestureTypes int tabScale, - @UCropActivity.GestureTypes int tabRotate, - @UCropActivity.GestureTypes int tabAspectRatio) { + @UCropActivity.GestureTypes int tabRotate, + @UCropActivity.GestureTypes int tabAspectRatio) { configuration.setAllowedGestures(new int[]{tabScale, tabRotate, tabAspectRatio}); return this; } @@ -237,7 +254,6 @@ public RxGalleryFinal cropAspectRatioOptions(int selectedByDefault, AspectRatio. /** * set to true to let user resize crop bounds (disabled by default) - * @param enabled */ public RxGalleryFinal cropFreeStyleCropEnabled(boolean enabled) { configuration.setFreestyleCropEnabled(enabled); @@ -246,7 +262,6 @@ public RxGalleryFinal cropFreeStyleCropEnabled(boolean enabled) { /** * set it to true if you want dimmed layer to have an oval inside - * @param isOval */ public RxGalleryFinal cropOvalDimmedLayer(boolean isOval) { configuration.setOvalDimmedLayer(isOval); @@ -255,66 +270,58 @@ public RxGalleryFinal cropOvalDimmedLayer(boolean isOval) { /** * 设置裁剪结果最大宽度和高度 - * @param width - * @param height */ public RxGalleryFinal cropMaxResultSize(@IntRange(from = 100) int width, @IntRange(from = 100) int height) { configuration.setMaxResultSize(width, height); return this; } - /** - * 设置显示标题 - * @return - */ - public RxGalleryFinal setTitle(String title) { - configuration.setTitle(title); - return this; - } /** * 设置回调 - * @param rxBusResultSubscriber - * @return */ - public RxGalleryFinal subscribe(@NonNull RxBusResultSubscriber rxBusResultSubscriber) { - this.rxBusResultSubscriber = (RxBusResultSubscriber) rxBusResultSubscriber; + public RxGalleryFinal subscribe(@NonNull RxBusResultDisposable rxBusResultSubscriber) { + this.isRadioDisposable = (RxBusResultDisposable) rxBusResultSubscriber; return this; } - public void openGallery(){ + public void openGallery() { + //提示 + ModelUtils.logDebug(); execute(); } + /** + * 执行 + */ private void execute() { Context context = configuration.getContext(); - if(context == null) { + if (context == null) { return; } - if(!StorageUtils.existSDcard()){ + if (!StorageUtils.existSDcard()) { + Logger.i("没有找到SD卡"); Toast.makeText(context, "没有找到SD卡", Toast.LENGTH_SHORT).show(); return; } - if(configuration.getImageLoader() == null) { - throw new UnknownImageLoaderTypeException(); + if (configuration.getImageLoader() == null) { + throw new NullPointerException("imageLoader == null , please check imageLoader"); } - - if(rxBusResultSubscriber == null){ + if (isRadioDisposable == null) { return; } - - Subscription subscription; - if(configuration.isRadio()) { - subscription = RxBus.getDefault() + Disposable disposable; + if (configuration.isRadio()) { + disposable = RxBus.getDefault() .toObservable(ImageRadioResultEvent.class) - .subscribe(rxBusResultSubscriber); + .subscribeWith(isRadioDisposable); } else { - subscription = RxBus.getDefault() + disposable = RxBus.getDefault() .toObservable(ImageMultipleResultEvent.class) - .subscribe(rxBusResultSubscriber); + .subscribeWith(isRadioDisposable); } - RxBus.getDefault().add(subscription); + RxBus.getDefault().add(disposable); Intent intent = new Intent(context, MediaActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); @@ -324,4 +331,5 @@ private void execute() { context.startActivity(intent); } + } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/RxGalleryFinalApi.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/RxGalleryFinalApi.java new file mode 100644 index 00000000..8a09a152 --- /dev/null +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/RxGalleryFinalApi.java @@ -0,0 +1,579 @@ +package cn.finalteam.rxgalleryfinal; + +import android.app.Activity; +import android.content.ContentValues; +import android.content.Intent; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.os.Environment; +import android.provider.MediaStore; +import android.support.v4.app.Fragment; +import android.text.TextUtils; +import android.widget.Toast; + +import com.yalantis.ucrop.UCrop; +import com.yalantis.ucrop.UCropActivity; + +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import java.util.Random; + +import cn.finalteam.rxgalleryfinal.imageloader.ImageLoaderType; +import cn.finalteam.rxgalleryfinal.rxbus.RxBusResultDisposable; +import cn.finalteam.rxgalleryfinal.rxbus.event.ImageMultipleResultEvent; +import cn.finalteam.rxgalleryfinal.rxbus.event.ImageRadioResultEvent; +import cn.finalteam.rxgalleryfinal.ui.RxGalleryListener; +import cn.finalteam.rxgalleryfinal.ui.base.IMultiImageCheckedListener; +import cn.finalteam.rxgalleryfinal.ui.base.IRadioImageCheckedListener; +import cn.finalteam.rxgalleryfinal.ui.fragment.MediaGridFragment; +import cn.finalteam.rxgalleryfinal.utils.Logger; +import cn.finalteam.rxgalleryfinal.utils.MediaScanner; +import cn.finalteam.rxgalleryfinal.utils.SimpleDateUtils; + +/** + * 设置回调 + * Created by KARL-dujinyang on 2017-03-23 03-03-00. + */ +public class RxGalleryFinalApi { + public static final int TAKE_IMAGE_REQUEST_CODE = 19001; + private static String IMG_TYPE = "image/jpeg"; + public static File fileImagePath;//拍照图片 + public static File cropImagePath;//裁剪图片 + private static RxGalleryFinalApi mRxApi = new RxGalleryFinalApi(); + private static RxGalleryFinal rxGalleryFinal; + + + /** + * 默认使用 ImageLoaderType.GLIDE + */ + public static RxGalleryFinalApi getInstance(Activity context) { + if (context == null) { + throw new NullPointerException("context == null"); + } + rxGalleryFinal = RxGalleryFinal.with(context) + .imageLoader(ImageLoaderType.GLIDE) + .subscribe(null); + Logger.i("==========" + mRxApi + "====" + rxGalleryFinal); + return mRxApi; + } + + /** + * 单选图片 + * + * @param flag 标识是否开启裁剪 + * @Override protected void onEvent(ImageRadioResultEvent imageRadioResultEvent) throws Exception { + *

+ * } + * } + * @see new RxBusResultSubscriber() { + */ + public static RxGalleryFinalApi openRadioSelectImage(Activity context, RxBusResultDisposable rxBusResultDisposable, boolean flag) { + getInstance(context); + if (flag) { + rxGalleryFinal + .image() + .radio() + .imageLoader(ImageLoaderType.GLIDE) + .subscribe(rxBusResultDisposable) + .openGallery(); + } else { + rxGalleryFinal + .image() + .radio() + .crop() + .imageLoader(ImageLoaderType.GLIDE) + .subscribe(rxBusResultDisposable) + .openGallery(); + } + return mRxApi; + } + + /** + * 得到裁剪之后的事件 + * + * @return RxGalleryFinalApi + */ + public RxGalleryFinalApi onCropImageResult(IRadioImageCheckedListener listener) { + RxGalleryListener.getInstance().setRadioImageCheckedListener(listener); + return mRxApi; + } + + /** + * 得到裁剪之后的事件 + * + * @return RxGalleryFinalApi + */ + public static RxGalleryFinalApi onMultiImageResult(IMultiImageCheckedListener listener) { + RxGalleryListener.getInstance().setMultiImageCheckedListener(listener); + return mRxApi; + } + + /** + * 得到多选限制事件 + */ + public static RxGalleryFinalApi onCrop(boolean flag) { + if (rxGalleryFinal == null) + return null; + rxGalleryFinal.crop(flag); + return mRxApi; + } + + /** + * 单选默认设置 + */ + public RxGalleryFinalApi openGalleryRadioImgDefault(RxBusResultDisposable rxBusResultDisposable) { + Logger.i("----rxGalleryFinal---" + rxGalleryFinal); + if (rxGalleryFinal == null) + return null; + rxGalleryFinal + .image() + .radio() + .crop() + .imageLoader(ImageLoaderType.GLIDE) + .subscribe(rxBusResultDisposable) + .openGallery(); + return mRxApi; + } + + /** + * 得到多选限制事件 + */ + public static RxGalleryFinalApi openGallery() { + if (rxGalleryFinal == null) + return null; + rxGalleryFinal.openGallery(); + return mRxApi; + } + + /** + * 单选图片:默认开启全部 + * + * @Override protected void onEvent(ImageRadioResultEvent imageRadioResultEvent) throws Exception { + *

+ * } + * } + * @see new RxBusResultSubscriber() { + */ + public static void openRadioSelectImage(Activity context, RxBusResultDisposable rxBusResultDisposable) { + RxGalleryFinal + .with(context) + .image() + .radio() + .crop() + .imageLoader(ImageLoaderType.GLIDE) + .subscribe(rxBusResultDisposable) + .openGallery(); + } + + /** + * 多选图片:默认开启全部 + * + * @Override protected void onEvent(ImageRadioResultEvent imageRadioResultEvent) throws Exception { + *

+ * } + * } + * @see new RxBusResultSubscriber() { + */ + public static void openMultiSelectImage(Activity context, RxBusResultDisposable rxBusResultDisposable) { + RxGalleryFinal + .with(context) + .image() + .multiple() + .crop() + .imageLoader(ImageLoaderType.GLIDE) + .subscribe(rxBusResultDisposable) + .openGallery(); + } + + /** + * 多选图片: + * + * @Override protected void onEvent(ImageRadioResultEvent imageRadioResultEvent) throws Exception { + *

+ * } + * } + * @see new RxBusResultSubscriber() { + */ + public static void openMultiSelectImage(Activity context, int maxSize, RxBusResultDisposable rxBusResultDisposable) { + RxGalleryFinal + .with(context) + .image() + .maxSize(maxSize) + .multiple() + .crop() + .imageLoader(ImageLoaderType.GLIDE) + .subscribe(rxBusResultDisposable) + .openGallery(); + } + + /** + * 单选视频:默认开启全部 + * + * @Override protected void onEvent(ImageRadioResultEvent imageRadioResultEvent) throws Exception { + *

+ * } + * } + * @see new RxBusResultSubscriber() { + */ + public static void openRadioSelectVD(Activity context, RxBusResultDisposable rxBusResultDisposable) { + RxGalleryFinal + .with(context) + .multiple() + .video() + .imageLoader(ImageLoaderType.GLIDE) + .subscribe(rxBusResultDisposable) + .openGallery(); + } + + /** + * 多选视频 :默认开启全部 + * 默认选9个视频 + * + * @Override protected void onEvent(ImageRadioResultEvent imageRadioResultEvent) throws Exception { + *

+ * } + * } + * @see new RxBusResultSubscriber() { + */ + public static void openMultiSelectVD(Activity context, RxBusResultDisposable rxBusResultDisposable) { + RxGalleryFinal + .with(context) + .video() + .multiple() + .maxSize(9) + .imageLoader(ImageLoaderType.UNIVERSAL) + .subscribe(rxBusResultDisposable) + .openGallery(); + } + + /** + * 打开相机 + *

+ * fragment 或者 activity 直接传入 this, 内部处理 + *

+ * 这里的 Fragment 指的是 v4包下的Fragment + * + * @see Fragment + *

+ * M 以上的权限处理,拍照以及读取相册需要自行申请,这里不做处理 + *

+ * 返回值: -1 : 设备没有相机 + */ + public static int openZKCamera(Object activity) { + + if (activity == null) { + throw new NullPointerException("activity == null"); + } + Activity cameraActivity = null; + if (activity instanceof Activity) { + cameraActivity = (Activity) activity; + } + if (activity instanceof Fragment) { + Fragment fragment = (Fragment) activity; + cameraActivity = fragment.getActivity(); + } + assert cameraActivity != null; + Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + if (captureIntent.resolveActivity(cameraActivity.getPackageManager()) != null) { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA); + String imageName = "immqy_%s.jpg"; + String filename = String.format(imageName, dateFormat.format(new Date())); + File mImageStoreDir = new File(Environment.getExternalStorageDirectory(), "/DCIM/IMMQY/"); + if (!mImageStoreDir.exists()) { + mImageStoreDir.mkdirs(); + } + fileImagePath = new File(mImageStoreDir, filename); + String mImagePath = fileImagePath.getAbsolutePath(); + Logger.i("->mImagePath:" + mImagePath); + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { + captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(fileImagePath)); + } else { + ContentValues contentValues = new ContentValues(1); + contentValues.put(MediaStore.Images.Media.DATA, mImagePath); + contentValues.put(MediaStore.Images.Media.MIME_TYPE, IMG_TYPE); + Uri uri = cameraActivity.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues); + captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri); + } + if (activity instanceof Activity) { + cameraActivity.startActivityForResult(captureIntent, TAKE_IMAGE_REQUEST_CODE); + } + if (activity instanceof Fragment) { + Fragment fragment = (Fragment) activity; + fragment.startActivityForResult(captureIntent, TAKE_IMAGE_REQUEST_CODE); + } + return 0; + } else { + Toast.makeText(cameraActivity, R.string.gallery_device_camera_unable, Toast.LENGTH_SHORT).show(); + return -1; + } + } + + /** + * 处理拍照返回 + */ + public static void openZKCameraForResult(Activity context, MediaScanner.ScanCallback mediaScanner) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { + MediaScanner scanner = new MediaScanner(context); + scanner.scanFile(RxGalleryFinalApi.fileImagePath.getPath(), IMG_TYPE, mediaScanner); + } else { + ContentValues values = new ContentValues(); + values.put(MediaStore.Images.ImageColumns.TITLE, "title"); + values.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, "filename.jpg"); + values.put(MediaStore.Images.ImageColumns.DATE_TAKEN, System.currentTimeMillis()); + values.put(MediaStore.Images.ImageColumns.MIME_TYPE, IMG_TYPE); + values.put(MediaStore.Images.ImageColumns.ORIENTATION, 0); + values.put(MediaStore.Images.ImageColumns.DATA, RxGalleryFinalApi.fileImagePath.getPath()); + try { + Uri uri = context.getContentResolver().insert( + MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); + if (uri == null) { + Logger.e("Failed to insert MediaStore"); + } else { + context.sendBroadcast(new Intent( + "com.android.camera.NEW_PICTURE", uri)); + } + } catch (Exception e) { + Logger.e("Failed to write MediaStore" + e); + } + context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + RxGalleryFinalApi.fileImagePath.getPath()))); + } + } + + /** + * 快速生成图片的路径 + * + * @return 虚拟路径 + */ + public static String getModelPath() { + File fileImagePath = null; + try { + String imageName = "immqy_%s_%s.jpg"; + Random random = new Random(); + String filename = String.format(imageName, SimpleDateUtils.getNowTime(), "" + random.nextInt(1024)); + File mImageStoreDir = new File(Environment.getExternalStorageDirectory(), "/DCIM/IMMQY/"); + /* if(!mImageStoreDir.exists()){ + mImageStoreDir.mkdirs(); + }*/ + fileImagePath = new File(mImageStoreDir, filename); + //mImagePath = fileImagePath.getPath(); + Logger.i("Test Path:" + fileImagePath.getPath()); + } catch (Exception e) { + e.printStackTrace(); + Logger.e("e=>" + e.getMessage()); + } + return fileImagePath.getPath(); + } + + /** + * 裁剪指定的路径- + * onActivityResult或者其它地方调用RxGalleryFinalApi.cropActivityForResult方法去刷新图库 + * RxGalleryFinalApi.cropActivityForResult() + */ + public static void cropScannerForResult(Activity context, String outPPath, String inputPath) { + if (TextUtils.isEmpty(inputPath)) { + Logger.e("-裁剪没有图片-"); + return; + } + Uri outUri = Uri.fromFile(new File(outPPath)); + Uri inputUri = Uri.fromFile(new File(inputPath)); + Intent intent = new Intent(context, UCropActivity.class); + Bundle bundle = new Bundle(); + bundle.putParcelable(UCrop.EXTRA_OUTPUT_URI, outUri); + bundle.putParcelable(UCrop.EXTRA_INPUT_URI, inputUri); + cropImagePath = new File(outUri.getPath()); + Logger.i("输出:" + outUri.getPath()); + Logger.i("原图:" + inputUri.getPath()); + intent.putExtras(bundle); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivityForResult(intent, -1);//无效 + } + + /** + * 扫描指定的图片路径--刷新图库 + */ + public static void cropActivityForResult(Activity context, MediaScanner.ScanCallback imgScanner) { + if (cropImagePath != null) { + MediaScanner scanner = new MediaScanner(context); + scanner.scanFile(RxGalleryFinalApi.cropImagePath.getPath(), IMG_TYPE, imgScanner); + } + } + + /** + * 扫描指定的图片路径--刷新图库 + * + * @param path 路径 + */ + public static void cropActivityForResult(Activity context, String path, MediaScanner.ScanCallback imgScanner) { + if (cropImagePath != null) { + MediaScanner scanner = new MediaScanner(context); + scanner.scanFile(path.trim(), IMG_TYPE, imgScanner); + } + } + + /** + * 设置图片存储的路径 + * + * @param file 返回原来的File + */ + public static File setImgSaveRxDir(File file) { + MediaGridFragment.setImageStoreDir(file); + return file; + } + //***********************************************************************// + + /** + * 设置图片存储到sd卡 -- 取文件夹名称 + */ + public static void setImgSaveRxSDCard(String name) { + MediaGridFragment.setImageStoreDir(name); + } + + /** + * 设置裁剪存储的路径 + * + * @param file 返回原来的File + */ + public static File setImgSaveRxCropDir(File file) { + MediaGridFragment.setImageStoreCropDir(file); + return file; + } + + /** + * 设置裁剪存储到sd卡 -- 取文件夹名称 + */ + public static void setImgSaveRxCropSDCard(String name) { + MediaGridFragment.setImageStoreCropDir(name); + } + + /** + * 获取裁剪存储的路径 + */ + public static String getImgSaveRxCropDirByStr() { + return MediaGridFragment.getImageStoreCropDirByStr(); + } + + /** + * 获取裁剪存储的路径 + * + * @return String + */ + public static File getImgSaveRxCropDirByFile() { + return MediaGridFragment.getImageStoreCropDirByFile(); + } + + /** + * 获取图片存储的路径 + * + * @return String 路径 + */ + public static String getImgSaveRxDirByStr() { + return MediaGridFragment.getImageStoreDirByStr(); + } + + /** + * 获取图片存储的路径 + * + * @return File 路径 + */ + public static File getImgSaveRxDirByFile() { + return MediaGridFragment.getImageStoreDirByFile(); + } + + /** + * 设置打开的类型和方式--多选默认9张图 + * setType(SelectRXType.TYPE_IMAGE,SelectRXType.TYPE_SELECT_RADIO); + * setType(SelectRXType.TYPE_VIDEO,SelectRXType.TYPE_SELECT_RADIO); + * + * @param type 图片或者视频 + * @param mt 单选或者多选 .多选默认9张图 + */ + public RxGalleryFinalApi setType(int type, int mt) { + switch (type) { + case SelectRXType.TYPE_IMAGE: + rxGalleryFinal.image(); + break; + case SelectRXType.TYPE_VIDEO: + rxGalleryFinal.video(); + break; + default: + Logger.e("open type is error!!!"); + break; + } + switch (mt) { + case SelectRXType.TYPE_SELECT_RADIO: + rxGalleryFinal.radio(); + break; + case SelectRXType.TYPE_SELECT_MULTI: + rxGalleryFinal.multiple(); + rxGalleryFinal.maxSize(9); + break; + default: + Logger.e("open mt is error!!!"); + break; + } + return mRxApi; + } + + /** + * 设置单选的按钮事件 + */ + public RxGalleryFinalApi setImageRadioResultEvent(RxBusResultDisposable t) { + rxGalleryFinal.image(); + rxGalleryFinal.subscribe(t); + return mRxApi; + } + + /** + * 设置多选的按钮事件 + */ + public RxGalleryFinalApi setImageMultipleResultEvent(RxBusResultDisposable t) { + rxGalleryFinal.image(); + rxGalleryFinal.subscribe(t); + return mRxApi; + } + + /** + * 设置视频单选的按钮事件 + */ + public RxGalleryFinalApi setVDRadioResultEvent(RxBusResultDisposable t) { + rxGalleryFinal.video(); + rxGalleryFinal.subscribe(t); + return mRxApi; + } + + /** + * 设置视频多选的按钮事件 + */ + public RxGalleryFinalApi setVDMultipleResultEvent(RxBusResultDisposable t) { + rxGalleryFinal.video(); + rxGalleryFinal.subscribe(t); + return mRxApi; + } + + public RxGalleryFinalApi setCrop() { + rxGalleryFinal.crop(); + return mRxApi; + } + + /** + * 直接打开默认设置好的参数 + */ + public RxGalleryFinalApi open() { + rxGalleryFinal.openGallery(); + return mRxApi; + } + + /** + * 选择类型 + */ + public static class SelectRXType { + public static final int TYPE_IMAGE = 801; + public static final int TYPE_VIDEO = 702; + public static final int TYPE_SELECT_RADIO = 1; + public static final int TYPE_SELECT_MULTI = 2; + } + +} \ No newline at end of file diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/imageloader/AbsImageLoader.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/imageloader/AbsImageLoader.java index c461d05a..2a4d1e92 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/imageloader/AbsImageLoader.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/imageloader/AbsImageLoader.java @@ -1,5 +1,6 @@ package cn.finalteam.rxgalleryfinal.imageloader; +import android.content.Context; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; @@ -7,11 +8,18 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/6/17 下午1:05 */ public interface AbsImageLoader { - void displayImage(Object context, String path, - FixImageView imageView, Drawable defaultDrawable, Bitmap.Config config, - boolean resize, int width, int height, int rotate); + void displayImage(Context context, + String path, + FixImageView imageView, + Drawable defaultDrawable, + Bitmap.Config config, + boolean resize, + boolean isGif, + int width, + int height, + int rotate); } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/imageloader/FrescoImageLoader.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/imageloader/FrescoImageLoader.java index bd2527c3..3501c320 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/imageloader/FrescoImageLoader.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/imageloader/FrescoImageLoader.java @@ -7,6 +7,7 @@ import android.graphics.drawable.Drawable; import android.net.Uri; import android.view.MotionEvent; +import android.widget.RelativeLayout; import com.facebook.common.util.UriUtil; import com.facebook.drawee.backends.pipeline.Fresco; @@ -14,21 +15,47 @@ import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder; import com.facebook.drawee.interfaces.DraweeController; import com.facebook.drawee.view.DraweeHolder; +import com.facebook.drawee.view.SimpleDraweeView; import com.facebook.imagepipeline.common.ResizeOptions; +import com.facebook.imagepipeline.common.RotationOptions; import com.facebook.imagepipeline.request.ImageRequest; import com.facebook.imagepipeline.request.ImageRequestBuilder; import cn.finalteam.rxgalleryfinal.ui.widget.FixImageView; +import cn.finalteam.rxgalleryfinal.ui.widget.SquareRelativeLayout; /** - * Created by pengjianbo on 2016/8/13 0013. + * Created by pengjianbo Dujinyang on 2016/8/13 0013. */ public class FrescoImageLoader implements AbsImageLoader { private DraweeHolder draweeHolder; + public static void setImageSmall(String url, + SimpleDraweeView simpleDraweeView, + int width, + int height, + SquareRelativeLayout relativeLayout, boolean playGif) { + + Uri uri = Uri.parse(url); + ImageRequest request = ImageRequestBuilder + .newBuilderWithSource(uri) + .setRotationOptions(RotationOptions.autoRotate()) + .setResizeOptions(new ResizeOptions(width, height)) + .setLowestPermittedRequestLevel(ImageRequest.RequestLevel.FULL_FETCH) + .build(); + DraweeController controller = Fresco.newDraweeControllerBuilder() + .setTapToRetryEnabled(true) + .setImageRequest(request) + .setAutoPlayAnimations(playGif) + .setOldController(simpleDraweeView.getController()) + .build(); + relativeLayout.setLayoutParams(new RelativeLayout.LayoutParams(width - 5, height)); + simpleDraweeView.setController(controller); + } + private void init(Context ctx, Drawable defaultDrawable) { - if(draweeHolder == null) { + if (draweeHolder == null) { Resources resources = ctx.getResources(); GenericDraweeHierarchy hierarchy = new GenericDraweeHierarchyBuilder(resources) .setPlaceholderImage(defaultDrawable) @@ -39,9 +66,16 @@ private void init(Context ctx, Drawable defaultDrawable) { } @Override - public void displayImage(Object context, String path, FixImageView imageView, Drawable defaultDrawable, Bitmap.Config config, boolean resize, int width, int height, int rotate) { - Context ctx = (Context) context; - init(ctx, defaultDrawable); + public void displayImage(Context context, + String path, + FixImageView imageView, + Drawable defaultDrawable, + Bitmap.Config config, + boolean resize, boolean isGif, + int width, + int height, + int rotate) { + init(context, defaultDrawable); imageView.setOnImageViewListener(new FixImageView.OnImageViewListener() { @Override @@ -56,10 +90,7 @@ public void onAttach() { @Override public boolean verifyDrawable(Drawable dr) { - if (dr == draweeHolder.getHierarchy().getTopLevelDrawable()) { - return true; - } - return false; + return dr == draweeHolder.getHierarchy().getTopLevelDrawable(); } @Override @@ -83,7 +114,7 @@ public boolean onTouchEvent(MotionEvent event) { .build(); ImageRequestBuilder builder = ImageRequestBuilder.newBuilderWithSource(uri) .setAutoRotateEnabled(true); - if(resize){ + if (resize) { builder.setResizeOptions(new ResizeOptions(width, height)); } ImageRequest request = builder.build(); diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/imageloader/GlideImageLoader.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/imageloader/GlideImageLoader.java index ee258c9e..857a3834 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/imageloader/GlideImageLoader.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/imageloader/GlideImageLoader.java @@ -4,32 +4,61 @@ import android.graphics.Bitmap; import android.graphics.drawable.Drawable; -import com.bumptech.glide.DrawableRequestBuilder; import com.bumptech.glide.Glide; import com.bumptech.glide.load.engine.DiskCacheStrategy; -import java.io.File; - import cn.finalteam.rxgalleryfinal.imageloader.rotate.RotateTransformation; import cn.finalteam.rxgalleryfinal.ui.widget.FixImageView; /** - * Created by pengjianbo on 2016/8/13 0013. + * Created by pengjianbo Dujinyang on 2016/8/13 0013. */ public class GlideImageLoader implements AbsImageLoader { @Override - public void displayImage(Object context, String path, FixImageView imageView, Drawable defaultDrawable, Bitmap.Config config, boolean resize, int width, int height, int rotate) { - Context ctx = (Context) context; - DrawableRequestBuilder builder = Glide.with(ctx) - .load(new File(path)) - .placeholder(defaultDrawable); - if(resize) { - builder = builder.override(width, height); - } - builder.crossFade() - .transform(new RotateTransformation(ctx, rotate)) - .diskCacheStrategy(DiskCacheStrategy.NONE) - .into(imageView); + public void displayImage(Context context, String path, FixImageView imageView, Drawable defaultDrawable, Bitmap.Config config, boolean resize, boolean isGif, int width, int height, int rotate) { +// DrawableRequestBuilder builder; +// if (path != null) { +// builder = Glide.with(context) +// .load(new File(path)). +// .placeholder(defaultDrawable); +// +// } else { +// builder = Glide.with(context) +// .load(new File("/sdcard")) +// .placeholder(defaultDrawable); +// } +// if (resize) { +// builder = builder.override(width, height); +// } +// builder +// .crossFade() +// .transform(new RotateTransformation(context, rotate)) +// .diskCacheStrategy(DiskCacheStrategy.NONE) +// .into(imageView); + + if (isGif) { + Glide + .with(context) + .load(path) + .placeholder(defaultDrawable) + .error(defaultDrawable) + .override(width, height) + .crossFade() + .transform(new RotateTransformation(context, rotate)) + .diskCacheStrategy(DiskCacheStrategy.NONE) + .into(imageView); + } else { + Glide + .with(context) + .load(path) + .asBitmap() + .placeholder(defaultDrawable) + .error(defaultDrawable) + .override(width, height) + .transform(new RotateTransformation(context, rotate)) + .diskCacheStrategy(DiskCacheStrategy.NONE) + .into(imageView); + } } } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/imageloader/ImageLoaderType.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/imageloader/ImageLoaderType.java index 412c1df0..d211a008 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/imageloader/ImageLoaderType.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/imageloader/ImageLoaderType.java @@ -2,9 +2,9 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/7/25 下午3:36 */ public enum ImageLoaderType { - PICASSO,GLIDE,FRESCO,UNIVERSAL + PICASSO, GLIDE, FRESCO, UNIVERSAL } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/imageloader/PicassoImageLoader.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/imageloader/PicassoImageLoader.java index c4267a67..15eec135 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/imageloader/PicassoImageLoader.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/imageloader/PicassoImageLoader.java @@ -14,16 +14,16 @@ /** * Desction: - * Author:pengjianbo + * .centerCrop() 预览大图 + * Author:dujinyang * Date:16/6/17 下午1:23 */ public class PicassoImageLoader implements AbsImageLoader { + @Override - public void displayImage(Object context, String path, FixImageView imageView, - Drawable defaultDrawable, Bitmap.Config config, boolean resize, int width, int height, int rotate) { - Context ctx = (Context) context; - RequestCreator creator = Picasso.with(ctx) + public void displayImage(Context context, String path, FixImageView imageView, Drawable defaultDrawable, Bitmap.Config config, boolean resize, boolean isGif, int width, int height, int rotate) { + RequestCreator creator = Picasso.with(context) .load(new File(path)) .placeholder(defaultDrawable) .error(defaultDrawable) @@ -31,9 +31,10 @@ public void displayImage(Object context, String path, FixImageView imageView, .networkPolicy(NetworkPolicy.NO_STORE) .config(config) .tag(context); - if(resize){ - creator = creator.resize(width, height); + if (resize) { + creator = creator.resize(width, height) + .centerCrop(); } - creator.into(imageView); + creator.into(imageView); } } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/imageloader/UniversalImageLoader.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/imageloader/UniversalImageLoader.java index 9946526a..505eafd3 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/imageloader/UniversalImageLoader.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/imageloader/UniversalImageLoader.java @@ -1,5 +1,6 @@ package cn.finalteam.rxgalleryfinal.imageloader; +import android.content.Context; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; @@ -11,23 +12,28 @@ import cn.finalteam.rxgalleryfinal.ui.widget.FixImageView; /** - * Created by pengjianbo on 2016/8/13 0013. + * Created by pengjianbo Dujinyang on 2016/8/13 0013. */ public class UniversalImageLoader implements AbsImageLoader { + private DisplayImageOptions displayImageOptions; + @Override - public void displayImage(Object context, String path, FixImageView imageView, Drawable defaultDrawable, Bitmap.Config config, boolean resize, int width, int height, int rotate) { - DisplayImageOptions options = new DisplayImageOptions.Builder() - .cacheOnDisk(false) - .bitmapConfig(config) - .showImageOnFail(defaultDrawable) - .showImageOnLoading(defaultDrawable) - .showImageForEmptyUri(defaultDrawable) - .build(); + public void displayImage(Context context, String path, FixImageView imageView, Drawable defaultDrawable, Bitmap.Config config, boolean resize, boolean isGif, int width, int height, int rotate) { + if (displayImageOptions == null) { + displayImageOptions = new DisplayImageOptions.Builder() + .cacheOnDisk(false) + .cacheInMemory(true) + .bitmapConfig(config) + .showImageOnFail(defaultDrawable) + .showImageOnLoading(defaultDrawable) + .showImageForEmptyUri(defaultDrawable) + .build(); + } ImageSize imageSize = null; - if(resize) { + if (resize) { imageSize = new ImageSize(width, height); } - ImageLoader.getInstance().displayImage("file://" + path, new ImageViewAware(imageView), options, imageSize, null, null); + ImageLoader.getInstance().displayImage("file://" + path, new ImageViewAware(imageView), displayImageOptions, imageSize, null, null); } } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/interactor/MediaBucketFactoryInteractor.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/interactor/MediaBucketFactoryInteractor.java index 7fafe7d2..8119f3f9 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/interactor/MediaBucketFactoryInteractor.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/interactor/MediaBucketFactoryInteractor.java @@ -6,14 +6,14 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/7/4 下午8:24 */ public interface MediaBucketFactoryInteractor { + void generateBuckets(); + interface OnGenerateBucketListener { void onFinished(List list); } - - void generateBuckets(); } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/interactor/MediaSrcFactoryInteractor.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/interactor/MediaSrcFactoryInteractor.java index ee522ccd..31056bcb 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/interactor/MediaSrcFactoryInteractor.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/interactor/MediaSrcFactoryInteractor.java @@ -6,21 +6,18 @@ /** * Desction:媒体资源工厂 - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/5/14 上午11:06 */ public interface MediaSrcFactoryInteractor { - interface OnGenerateMediaListener { - void onFinished(String bucketId, int pageSize, int currentOffset, List list); - } - /** * 生产资源 - * @param bucketId - * @param page - * @param limit */ void generateMeidas(String bucketId, int page, int limit); + interface OnGenerateMediaListener { + void onFinished(String bucketId, int pageSize, int currentOffset, List list); + } + } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/interactor/impl/MediaBucketFactoryInteractorImpl.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/interactor/impl/MediaBucketFactoryInteractorImpl.java index 635b2c90..93f5c7cb 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/interactor/impl/MediaBucketFactoryInteractorImpl.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/interactor/impl/MediaBucketFactoryInteractorImpl.java @@ -1,5 +1,6 @@ package cn.finalteam.rxgalleryfinal.interactor.impl; + import android.content.Context; import java.util.List; @@ -7,21 +8,22 @@ import cn.finalteam.rxgalleryfinal.bean.BucketBean; import cn.finalteam.rxgalleryfinal.interactor.MediaBucketFactoryInteractor; import cn.finalteam.rxgalleryfinal.utils.MediaUtils; -import rx.Observable; -import rx.Observer; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; +import io.reactivex.Observable; +import io.reactivex.ObservableOnSubscribe; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.observers.DisposableObserver; +import io.reactivex.schedulers.Schedulers; /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/7/4 下午8:29 */ public class MediaBucketFactoryInteractorImpl implements MediaBucketFactoryInteractor { - private Context context; - private boolean isImage; - private OnGenerateBucketListener onGenerateBucketListener; + private final Context context; + private final boolean isImage; + private final OnGenerateBucketListener onGenerateBucketListener; public MediaBucketFactoryInteractorImpl(Context context, boolean isImage, OnGenerateBucketListener onGenerateBucketListener) { this.context = context; @@ -31,32 +33,32 @@ public MediaBucketFactoryInteractorImpl(Context context, boolean isImage, OnGene @Override public void generateBuckets() { - Observable.create((Observable.OnSubscribe>) subscriber -> { + Observable.create((ObservableOnSubscribe>) subscriber -> { List bucketBeanList = null; - if(isImage) { + if (isImage) { bucketBeanList = MediaUtils.getAllBucketByImage(context); } else { bucketBeanList = MediaUtils.getAllBucketByVideo(context); } subscriber.onNext(bucketBeanList); - subscriber.onCompleted(); + subscriber.onComplete(); }) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Observer>() { - @Override - public void onCompleted() { - } + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new DisposableObserver>() { + @Override + public void onComplete() { + } - @Override - public void onError(Throwable e) { - onGenerateBucketListener.onFinished(null); - } + @Override + public void onError(Throwable e) { + onGenerateBucketListener.onFinished(null); + } - @Override - public void onNext(List bucketBeanList) { - onGenerateBucketListener.onFinished(bucketBeanList); - } - }); + @Override + public void onNext(List bucketBeanList) { + onGenerateBucketListener.onFinished(bucketBeanList); + } + }); } } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/interactor/impl/MediaSrcFactoryInteractorImpl.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/interactor/impl/MediaSrcFactoryInteractorImpl.java index 5089fefa..15e08e5e 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/interactor/impl/MediaSrcFactoryInteractorImpl.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/interactor/impl/MediaSrcFactoryInteractorImpl.java @@ -7,21 +7,22 @@ import cn.finalteam.rxgalleryfinal.bean.MediaBean; import cn.finalteam.rxgalleryfinal.interactor.MediaSrcFactoryInteractor; import cn.finalteam.rxgalleryfinal.utils.MediaUtils; -import rx.Observable; -import rx.Observer; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; +import io.reactivex.Observable; +import io.reactivex.ObservableOnSubscribe; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.observers.DisposableObserver; +import io.reactivex.schedulers.Schedulers; /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/5/14 上午11:08 */ public class MediaSrcFactoryInteractorImpl implements MediaSrcFactoryInteractor { - Context context; - OnGenerateMediaListener onGenerateMediaListener; - boolean isImage; + private final Context context; + private final OnGenerateMediaListener onGenerateMediaListener; + private final boolean isImage; public MediaSrcFactoryInteractorImpl(Context context, boolean isImage, OnGenerateMediaListener onGenerateMediaListener) { this.context = context; @@ -31,32 +32,32 @@ public MediaSrcFactoryInteractorImpl(Context context, boolean isImage, OnGenerat @Override public void generateMeidas(final String bucketId, final int page, final int limit) { - Observable.create((Observable.OnSubscribe>) subscriber -> { + Observable.create((ObservableOnSubscribe>) subscriber -> { List mediaBeanList = null; - if(isImage) { + if (isImage) { mediaBeanList = MediaUtils.getMediaWithImageList(context, bucketId, page, limit); } else { mediaBeanList = MediaUtils.getMediaWithVideoList(context, bucketId, page, limit); } subscriber.onNext(mediaBeanList); - subscriber.onCompleted(); + subscriber.onComplete(); }) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Observer>() { - @Override - public void onCompleted() { - } - - @Override - public void onError(Throwable e) { - onGenerateMediaListener.onFinished(bucketId, page, limit, null); - } - - @Override - public void onNext(List mediaBeenList) { - onGenerateMediaListener.onFinished(bucketId, page, limit, mediaBeenList); - } - }); + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new DisposableObserver>() { + @Override + public void onComplete() { + } + + @Override + public void onError(Throwable e) { + onGenerateMediaListener.onFinished(bucketId, page, limit, null); + } + + @Override + public void onNext(List mediaBeenList) { + onGenerateMediaListener.onFinished(bucketId, page, limit, mediaBeenList); + } + }); } } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/RxBus.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/RxBus.java index 72c0ebe9..fda088bf 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/RxBus.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/RxBus.java @@ -3,30 +3,29 @@ import java.util.HashMap; import java.util.Map; -import rx.Observable; -import rx.Subscriber; -import rx.Subscription; -import rx.subjects.PublishSubject; -import rx.subjects.SerializedSubject; -import rx.subjects.Subject; -import rx.subscriptions.CompositeSubscription; +import io.reactivex.Observable; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.disposables.Disposable; +import io.reactivex.subjects.PublishSubject; +import io.reactivex.subjects.Subject; + /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/7/22 下午2:40 */ public class RxBus { private static volatile RxBus mInstance; - private final Subject mBus; + private final Subject mBus; private final Map, Object> mStickyEventMap; - private final CompositeSubscription mSubscriptions; + private final CompositeDisposable mDisposable; - public RxBus() { - mBus = new SerializedSubject<>(PublishSubject.create()); - mSubscriptions = new CompositeSubscription(); + private RxBus() { + mBus = PublishSubject.create().toSerialized(); + mDisposable = new CompositeDisposable(); mStickyEventMap = new HashMap<>(); } @@ -66,31 +65,29 @@ public void reset() { mInstance = null; } + /** * 是否被取消订阅 - * @return */ public boolean isUnsubscribed() { - return mSubscriptions.isUnsubscribed(); + return mDisposable.isDisposed(); } /** * 添加订阅 - * @param s */ - public void add(Subscription s) { + public void add(Disposable s) { if (s != null) { - mSubscriptions.add(s); + mDisposable.add(s); } } /** * 移除订阅 - * @param s */ - public void remove(Subscription s) { + public void remove(Disposable s) { if (s != null) { - mSubscriptions.remove(s); + mDisposable.remove(s); } } @@ -98,25 +95,16 @@ public void remove(Subscription s) { * 清除所有订阅 */ public void clear() { - mSubscriptions.clear(); + mDisposable.clear(); } /** * 取消订阅 */ public void unsubscribe() { - mSubscriptions.unsubscribe(); - } - - /** - * 判断是否有订阅者 - * @return - */ - public boolean hasSubscriptions() { - return mSubscriptions.hasSubscriptions(); + mDisposable.dispose(); } - /** * 发送一个新Sticky事件 */ @@ -136,12 +124,7 @@ public Observable toObservableSticky(final Class eventType) { final Object event = mStickyEventMap.get(eventType); if (event != null) { - return Observable.merge(observable, Observable.create(new Observable.OnSubscribe() { - @Override - public void call(Subscriber subscriber) { - subscriber.onNext(eventType.cast(event)); - } - })); + return Observable.merge(observable, Observable.create(subscriber -> subscriber.onNext(eventType.cast(event)))); } else { return observable; } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/RxBusSubscriber.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/RxBusDisposable.java similarity index 69% rename from library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/RxBusSubscriber.java rename to library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/RxBusDisposable.java index 74a5b612..146afb58 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/RxBusSubscriber.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/RxBusDisposable.java @@ -1,14 +1,14 @@ package cn.finalteam.rxgalleryfinal.rxbus; import cn.finalteam.rxgalleryfinal.utils.Logger; -import rx.Subscriber; +import io.reactivex.observers.DisposableObserver; /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/7/22 下午2:40 */ -public abstract class RxBusSubscriber extends Subscriber { +public abstract class RxBusDisposable extends DisposableObserver { @Override public void onNext(T t) { @@ -16,11 +16,14 @@ public void onNext(T t) { onEvent(t); } catch (Exception e) { e.printStackTrace(); + onError(e); } } + @Override - public void onCompleted() { + public void onComplete() { + } @Override @@ -29,4 +32,5 @@ public void onError(Throwable e) { } protected abstract void onEvent(T t) throws Exception; + } \ No newline at end of file diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/RxBusResultSubscriber.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/RxBusResultDisposable.java similarity index 54% rename from library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/RxBusResultSubscriber.java rename to library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/RxBusResultDisposable.java index bee941ef..ec7c0bc8 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/RxBusResultSubscriber.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/RxBusResultDisposable.java @@ -4,8 +4,8 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/8/1 下午11:11 */ -public abstract class RxBusResultSubscriber extends RxBusSubscriber { +public abstract class RxBusResultDisposable extends RxBusDisposable { } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/RequestStorageReadAccessPermissionEvent.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/RequestStorageReadAccessPermissionEvent.java index 9f3223e7..b9dc22b3 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/RequestStorageReadAccessPermissionEvent.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/RequestStorageReadAccessPermissionEvent.java @@ -2,19 +2,28 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/7/30 下午11:23 */ public class RequestStorageReadAccessPermissionEvent { - private boolean success; + public static final int TYPE_CAMERA = 0; + public static final int TYPE_WRITE = 1; - public RequestStorageReadAccessPermissionEvent(boolean success) { + private final boolean success; + private final int type; + + public RequestStorageReadAccessPermissionEvent(boolean success, int type) { this.success = success; + this.type = type; } public boolean isSuccess() { return success; } + public int getType() { + return type; + } + } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxjob/Job.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxjob/Job.java index 9573eba4..3274fe11 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxjob/Job.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxjob/Job.java @@ -4,31 +4,33 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/7/31 上午9:15 */ public interface Job { - public enum Result { + Result onRunJob(); + + enum Result { SUCCESS(), FAILURE(); private Object data; - Result(){ - } - - public void setResultData(Object data){ - this.data = data; + Result() { } public Object getResultData() { return data; } + + public void setResultData(Object data) { + this.data = data; + } } - public class Params { - private Object data; - private String tag; + class Params { + private final Object data; + private final String tag; public Params(@NonNull String tag, Object requestData) { this.tag = tag; @@ -43,6 +45,4 @@ public Object getRequestData() { return data; } } - - Result onRunJob(); } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxjob/JobCreator.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxjob/JobCreator.java index a7710c06..38185d04 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxjob/JobCreator.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxjob/JobCreator.java @@ -2,7 +2,7 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/7/31 上午9:10 */ public interface JobCreator { diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxjob/JobManager.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxjob/JobManager.java index 36eb3d42..d09a79b3 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxjob/JobManager.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxjob/JobManager.java @@ -3,71 +3,64 @@ import java.util.Queue; import java.util.concurrent.LinkedBlockingQueue; -import rx.Observable; -import rx.Observer; -import rx.Subscriber; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; +import io.reactivex.Observable; +import io.reactivex.ObservableOnSubscribe; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.observers.DisposableObserver; +import io.reactivex.schedulers.Schedulers; + /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/7/31 上午9:12 */ -public class JobManager { +class JobManager { private final Queue jobQueue; private boolean queueFree = true; - public JobManager() { + JobManager() { jobQueue = new LinkedBlockingQueue<>(); } - public void addJob(Job job) { - try { - if (jobQueue.isEmpty() && queueFree) { - jobQueue.offer(job); - start(); - } else { - jobQueue.offer(job); - } - }catch (Exception e){} - + void addJob(Job job) { + if (jobQueue.isEmpty() && queueFree) { + jobQueue.offer(job); + start(); + } else { + jobQueue.offer(job); + } } private void start() { - Observable.create(new Observable.OnSubscribe() { - @Override - public void call(Subscriber subscriber) { - queueFree = false; - Job job; - while ((job = jobQueue.poll()) != null){ - job.onRunJob(); - } - subscriber.onCompleted(); + Observable.create((ObservableOnSubscribe) subscriber -> { + queueFree = false; + Job job; + while ((job = jobQueue.poll()) != null) { + job.onRunJob(); } + subscriber.onComplete(); }) - .subscribeOn(Schedulers.newThread()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Observer() { - @Override - public void onCompleted() { - queueFree = true; - } + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new DisposableObserver() { + @Override + public void onComplete() { + queueFree = true; + } - @Override - public void onError(Throwable e) { - } + @Override + public void onError(Throwable e) { + } - @Override - public void onNext(Job job) { - } - }); + @Override + public void onNext(Job job) { + } + }); } public void clear() { - try { - jobQueue.clear(); - }catch (Exception e){} + jobQueue.clear(); } } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxjob/RxJob.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxjob/RxJob.java index 50525b82..6742daa9 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxjob/RxJob.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxjob/RxJob.java @@ -2,20 +2,20 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/7/31 上午9:09 */ public class RxJob { - private final JobManager jobManager; private static RxJob rxJob; + private final JobManager jobManager; - public RxJob() { + private RxJob() { jobManager = new JobManager(); } public static RxJob getDefault() { - if(rxJob == null){ + if (rxJob == null) { rxJob = new RxJob(); } return rxJob; diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxjob/job/ImageThmbnailJob.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxjob/job/ImageThmbnailJob.java index 2cfa64aa..dc3cbacf 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxjob/job/ImageThmbnailJob.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxjob/job/ImageThmbnailJob.java @@ -11,13 +11,13 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/7/31 上午11:46 */ public class ImageThmbnailJob implements Job { - private MediaBean mediaBean; - private Context context; + private final MediaBean mediaBean; + private final Context context; public ImageThmbnailJob(Context context, Params params) { this.context = context; @@ -29,10 +29,10 @@ public Result onRunJob() { String originalPath = mediaBean.getOriginalPath(); File bigThumFile = MediaUtils.createThumbnailBigFileName(context, originalPath); File smallThumFile = MediaUtils.createThumbnailSmallFileName(context, originalPath); - if(!smallThumFile.exists()){ + if (!bigThumFile.exists()) { BitmapUtils.createThumbnailBig(bigThumFile, originalPath); } - if(!bigThumFile.exists()){ + if (!smallThumFile.exists()) { BitmapUtils.createThumbnailSmall(smallThumFile, originalPath); } Result result = Result.SUCCESS; diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxjob/job/ImageThmbnailJobCreate.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxjob/job/ImageThmbnailJobCreate.java index 31ea4f63..43e53ed0 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxjob/job/ImageThmbnailJobCreate.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxjob/job/ImageThmbnailJobCreate.java @@ -8,14 +8,13 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/7/31 上午11:46 */ public class ImageThmbnailJobCreate implements JobCreator { - private MediaBean mediaBean; - private Context context; - private Job job; + private final MediaBean mediaBean; + private final Context context; public ImageThmbnailJobCreate(Context context, MediaBean mediaBean) { this.context = context; @@ -25,8 +24,7 @@ public ImageThmbnailJobCreate(Context context, MediaBean mediaBean) { @Override public Job create() { Job.Params params = new Job.Params(mediaBean.getOriginalPath(), mediaBean); - job = new ImageThmbnailJob(context, params); - return job; + return new ImageThmbnailJob(context, params); } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/RxGalleryListener.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/RxGalleryListener.java new file mode 100644 index 00000000..83cc6d3c --- /dev/null +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/RxGalleryListener.java @@ -0,0 +1,36 @@ +package cn.finalteam.rxgalleryfinal.ui; + +import cn.finalteam.rxgalleryfinal.ui.adapter.MediaGridAdapter; +import cn.finalteam.rxgalleryfinal.ui.base.IMultiImageCheckedListener; +import cn.finalteam.rxgalleryfinal.ui.base.IRadioImageCheckedListener; +import cn.finalteam.rxgalleryfinal.ui.fragment.MediaGridFragment; + +/** + * 处理回调监听 + * Created by KARL on 2017-03-17 04-42-25. + */ +public class RxGalleryListener { + + private static final class RxGalleryListenerHolder { + private static final RxGalleryListener RX_GALLERY_LISTENER = new RxGalleryListener(); + } + + public static RxGalleryListener getInstance() { + return RxGalleryListenerHolder.RX_GALLERY_LISTENER; + } + + /** + * 图片多选的事件 + */ + public void setMultiImageCheckedListener(IMultiImageCheckedListener checkedImageListener) { + MediaGridAdapter.setCheckedListener(checkedImageListener); + } + + + /** + * 图片单选的事件 + */ + public void setRadioImageCheckedListener(IRadioImageCheckedListener checkedImageListener) { + MediaGridFragment.setRadioListener(checkedImageListener); + } +} diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/activity/MediaActivity.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/activity/MediaActivity.java index 20253718..6bc500ec 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/activity/MediaActivity.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/activity/MediaActivity.java @@ -24,15 +24,15 @@ import cn.finalteam.rxgalleryfinal.R; import cn.finalteam.rxgalleryfinal.bean.MediaBean; import cn.finalteam.rxgalleryfinal.rxbus.RxBus; -import cn.finalteam.rxgalleryfinal.rxbus.RxBusSubscriber; +import cn.finalteam.rxgalleryfinal.rxbus.RxBusDisposable; import cn.finalteam.rxgalleryfinal.rxbus.event.BaseResultEvent; import cn.finalteam.rxgalleryfinal.rxbus.event.CloseRxMediaGridPageEvent; import cn.finalteam.rxgalleryfinal.rxbus.event.ImageMultipleResultEvent; import cn.finalteam.rxgalleryfinal.rxbus.event.MediaCheckChangeEvent; import cn.finalteam.rxgalleryfinal.rxbus.event.MediaViewPagerChangedEvent; +import cn.finalteam.rxgalleryfinal.rxbus.event.OpenMediaPageFragmentEvent; import cn.finalteam.rxgalleryfinal.rxbus.event.OpenMediaPreviewFragmentEvent; import cn.finalteam.rxgalleryfinal.rxbus.event.RequestStorageReadAccessPermissionEvent; -import cn.finalteam.rxgalleryfinal.rxbus.event.OpenMediaPageFragmentEvent; import cn.finalteam.rxgalleryfinal.rxjob.RxJob; import cn.finalteam.rxgalleryfinal.ui.fragment.MediaGridFragment; import cn.finalteam.rxgalleryfinal.ui.fragment.MediaPageFragment; @@ -41,16 +41,18 @@ import cn.finalteam.rxgalleryfinal.utils.OsCompat; import cn.finalteam.rxgalleryfinal.utils.ThemeUtils; import cn.finalteam.rxgalleryfinal.view.ActivityFragmentView; -import rx.Subscription; +import io.reactivex.disposables.Disposable; /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/5/7 上午10:01 */ public class MediaActivity extends BaseActivity implements ActivityFragmentView { public static final int REQUEST_STORAGE_READ_ACCESS_PERMISSION = 101; + public static final int REQUEST_STORAGE_WRITE_ACCESS_PERMISSION = 102; + public static final int REQUEST_CAMERA_ACCESS_PERMISSION = 103; private static final String EXTRA_CHECKED_LIST = EXTRA_PREFIX + ".CheckedList"; private static final String EXTRA_SELECTED_INDEX = EXTRA_PREFIX + ".SelectedIndex"; @@ -58,9 +60,9 @@ public class MediaActivity extends BaseActivity implements ActivityFragmentView private static final String EXTRA_PAGE_POSITION = EXTRA_PREFIX + ".PagePosition"; private static final String EXTRA_PREVIEW_POSITION = EXTRA_PREFIX + ".PreviewPosition"; - MediaGridFragment mMediaGridFragment; - MediaPageFragment mMediaPageFragment; - MediaPreviewFragment mMediaPreviewFragment; + private MediaGridFragment mMediaGridFragment; + private MediaPageFragment mMediaPageFragment; + private MediaPreviewFragment mMediaPreviewFragment; private Toolbar mToolbar; private TextView mTvToolbarTitle; @@ -81,12 +83,16 @@ public int getContentView() { @Override protected void onCreateOk(@Nullable Bundle savedInstanceState) { mMediaGridFragment = MediaGridFragment.newInstance(mConfiguration); - if(!mConfiguration.isRadio()) { - mTvOverAction.setOnClickListener(view -> { - if(mCheckedList != null && mCheckedList.size() > 0) { - BaseResultEvent event = new ImageMultipleResultEvent(mCheckedList); - RxBus.getDefault().post(event); - finish(); + if (!mConfiguration.isRadio()) { + mTvOverAction.setOnClickListener(v -> { + if (mMediaGridFragment != null && mMediaGridFragment.isShowRvBucketView()) { + mMediaGridFragment.hideRvBucketView(); + } else { + if (mCheckedList != null && mCheckedList.size() > 0) { + BaseResultEvent event = new ImageMultipleResultEvent(mCheckedList); + RxBus.getDefault().post(event); + finish(); + } } }); mTvOverAction.setVisibility(View.VISIBLE); @@ -95,8 +101,16 @@ protected void onCreateOk(@Nullable Bundle savedInstanceState) { } mCheckedList = new ArrayList<>(); List selectedList = mConfiguration.getSelectedList(); - if(selectedList != null && selectedList.size() > 0){ + if (selectedList != null && selectedList.size() > 0) { mCheckedList.addAll(selectedList); + if (mCheckedList.size() > 0) { + String text = getResources().getString(R.string.gallery_over_button_text_checked, mCheckedList.size(), mConfiguration.getMaxSize()); + mTvOverAction.setText(text); + mTvOverAction.setEnabled(true); + } else { + mTvOverAction.setText(R.string.gallery_over_button_text); + mTvOverAction.setEnabled(false); + } } showMediaGridFragment(); @@ -120,7 +134,7 @@ protected void setTheme() { mToolbar.setNavigationIcon(closeDrawable); int overButtonBg = ThemeUtils.resolveDrawableRes(this, R.attr.gallery_toolbar_over_button_bg); - if(overButtonBg != 0) { + if (overButtonBg != 0) { mTvOverAction.setBackgroundResource(overButtonBg); } else { OsCompat.setBackgroundDrawableCompat(mTvOverAction, createDefaultOverButtonBgDrawable()); @@ -165,11 +179,11 @@ protected void setTheme() { @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); - if(mCheckedList != null) { + if (mCheckedList != null) { outState.putParcelableArrayList(EXTRA_CHECKED_LIST, mCheckedList); } outState.putInt(EXTRA_SELECTED_INDEX, mSelectedIndex); - if(mPageMediaList != null) { + if (mPageMediaList != null) { outState.putParcelableArrayList(EXTRA_PAGE_MEDIA_LIST, mPageMediaList); } outState.putInt(EXTRA_PAGE_POSITION, mPagePosition); @@ -180,7 +194,7 @@ protected void onSaveInstanceState(Bundle outState) { protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); List list = savedInstanceState.getParcelableArrayList(EXTRA_CHECKED_LIST); - if(list != null && list.size() > 0){ + if (list != null && list.size() > 0) { mCheckedList.clear(); mCheckedList.addAll(list); } @@ -188,7 +202,7 @@ protected void onRestoreInstanceState(Bundle savedInstanceState) { mPagePosition = savedInstanceState.getInt(EXTRA_PAGE_POSITION); mPreviewPosition = savedInstanceState.getInt(EXTRA_PREVIEW_POSITION); mSelectedIndex = savedInstanceState.getInt(EXTRA_SELECTED_INDEX); - if(!mConfiguration.isRadio()) { + if (!mConfiguration.isRadio()) { switch (mSelectedIndex) { case 1: showMediaPageFragment(mPageMediaList, mPagePosition); @@ -216,14 +230,14 @@ public void showMediaGridFragment() { FragmentTransaction ft = getSupportFragmentManager().beginTransaction() .replace(R.id.fragment_container, mMediaGridFragment); - if(mMediaPreviewFragment != null) { - ft.hide(mMediaPreviewFragment); - } - if(mMediaPageFragment != null){ - ft.hide(mMediaPageFragment); - } + if (mMediaPreviewFragment != null) { + ft.hide(mMediaPreviewFragment); + } + if (mMediaPageFragment != null) { + ft.hide(mMediaPageFragment); + } ft.show(mMediaGridFragment) - .commit(); + .commit(); if(mConfiguration.getTitle()!=null){ mTvToolbarTitle.setText(mConfiguration.getTitle()); @@ -265,9 +279,9 @@ public void showMediaPreviewFragment() { } private void subscribeEvent() { - Subscription subscriptionOpenMediaPreviewEvent = RxBus.getDefault().toObservable(OpenMediaPreviewFragmentEvent.class) + Disposable subscriptionOpenMediaPreviewEvent = RxBus.getDefault().toObservable(OpenMediaPreviewFragmentEvent.class) .map(mediaPreviewEvent -> mediaPreviewEvent) - .subscribe(new RxBusSubscriber() { + .subscribeWith(new RxBusDisposable() { @Override protected void onEvent(OpenMediaPreviewFragmentEvent openMediaPreviewFragmentEvent) { mPreviewPosition = 0; @@ -277,19 +291,19 @@ protected void onEvent(OpenMediaPreviewFragmentEvent openMediaPreviewFragmentEve RxBus.getDefault().add(subscriptionOpenMediaPreviewEvent); - Subscription subscriptionMediaCheckChangeEvent = RxBus.getDefault().toObservable(MediaCheckChangeEvent.class) + Disposable subscriptionMediaCheckChangeEvent = RxBus.getDefault().toObservable(MediaCheckChangeEvent.class) .map(mediaCheckChangeEvent -> mediaCheckChangeEvent) - .subscribe(new RxBusSubscriber() { + .subscribeWith(new RxBusDisposable() { @Override protected void onEvent(MediaCheckChangeEvent mediaCheckChangeEvent) { MediaBean mediaBean = mediaCheckChangeEvent.getMediaBean(); - if(mCheckedList.contains(mediaBean)) { + if (mCheckedList.contains(mediaBean)) { mCheckedList.remove(mediaBean); } else { mCheckedList.add(mediaBean); } - if(mCheckedList.size() > 0){ + if (mCheckedList.size() > 0) { String text = getResources().getString(R.string.gallery_over_button_text_checked, mCheckedList.size(), mConfiguration.getMaxSize()); mTvOverAction.setText(text); mTvOverAction.setEnabled(true); @@ -301,14 +315,14 @@ protected void onEvent(MediaCheckChangeEvent mediaCheckChangeEvent) { }); RxBus.getDefault().add(subscriptionMediaCheckChangeEvent); - Subscription subscriptionMediaViewPagerChangedEvent = RxBus.getDefault().toObservable(MediaViewPagerChangedEvent.class) + Disposable subscriptionMediaViewPagerChangedEvent = RxBus.getDefault().toObservable(MediaViewPagerChangedEvent.class) .map(mediaViewPagerChangedEvent -> mediaViewPagerChangedEvent) - .subscribe(new RxBusSubscriber() { + .subscribeWith(new RxBusDisposable() { @Override protected void onEvent(MediaViewPagerChangedEvent mediaPreviewViewPagerChangedEvent) { int curIndex = mediaPreviewViewPagerChangedEvent.getCurIndex(); int totalSize = mediaPreviewViewPagerChangedEvent.getTotalSize(); - if(mediaPreviewViewPagerChangedEvent.isPreview()) { + if (mediaPreviewViewPagerChangedEvent.isPreview()) { mPreviewPosition = curIndex; } else { mPagePosition = curIndex; @@ -319,8 +333,8 @@ protected void onEvent(MediaViewPagerChangedEvent mediaPreviewViewPagerChangedEv }); RxBus.getDefault().add(subscriptionMediaViewPagerChangedEvent); - Subscription subscriptionCloseRxMediaGridPageEvent = RxBus.getDefault().toObservable(CloseRxMediaGridPageEvent.class) - .subscribe(new RxBusSubscriber() { + Disposable subscriptionCloseRxMediaGridPageEvent = RxBus.getDefault().toObservable(CloseRxMediaGridPageEvent.class) + .subscribeWith(new RxBusDisposable() { @Override protected void onEvent(CloseRxMediaGridPageEvent closeRxMediaGridPageEvent) throws Exception { finish(); @@ -328,8 +342,8 @@ protected void onEvent(CloseRxMediaGridPageEvent closeRxMediaGridPageEvent) thro }); RxBus.getDefault().add(subscriptionCloseRxMediaGridPageEvent); - Subscription subscriptionOpenMediaPageFragmentEvent = RxBus.getDefault().toObservable(OpenMediaPageFragmentEvent.class) - .subscribe(new RxBusSubscriber() { + Disposable subscriptionOpenMediaPageFragmentEvent = RxBus.getDefault().toObservable(OpenMediaPageFragmentEvent.class) + .subscribeWith(new RxBusDisposable() { @Override protected void onEvent(OpenMediaPageFragmentEvent openMediaPageFragmentEvent) { mPageMediaList = openMediaPageFragmentEvent.getMediaBeanList(); @@ -346,8 +360,12 @@ public List getCheckedList() { } private void backAction() { - if((mMediaPreviewFragment != null && mMediaPreviewFragment.isVisible()) - || (mMediaPageFragment != null &&mMediaPageFragment.isVisible())){ + if (mMediaGridFragment != null && mMediaGridFragment.isShowRvBucketView()) { + mMediaGridFragment.hideRvBucketView(); + return; + } + if ((mMediaPreviewFragment != null && mMediaPreviewFragment.isVisible()) + || (mMediaPageFragment != null && mMediaPageFragment.isVisible())) { showMediaGridFragment(); return; } @@ -356,7 +374,7 @@ private void backAction() { @Override public boolean onKeyDown(int keyCode, KeyEvent event) { - if(keyCode == KeyEvent.KEYCODE_BACK){ + if (keyCode == KeyEvent.KEYCODE_BACK) { backAction(); return true; } @@ -375,7 +393,7 @@ private StateListDrawable createDefaultOverButtonBgDrawable() { int dp12 = (int) ThemeUtils.applyDimensionDp(this, 12.f); int dp8 = (int) ThemeUtils.applyDimensionDp(this, 8.f); float dp4 = ThemeUtils.applyDimensionDp(this, 4.f); - float[] round = new float[] { dp4, dp4, dp4, dp4, dp4, dp4, dp4, dp4 }; + float[] round = new float[]{dp4, dp4, dp4, dp4, dp4, dp4, dp4, dp4}; ShapeDrawable pressedDrawable = new ShapeDrawable(new RoundRectShape(round, null, null)); pressedDrawable.setPadding(dp12, dp8, dp12, dp8); int pressedColor = ThemeUtils.resolveColor(this, R.attr.gallery_toolbar_over_button_pressed_color, R.color.gallery_default_toolbar_over_button_pressed_color); @@ -396,18 +414,31 @@ private StateListDrawable createDefaultOverButtonBgDrawable() { @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); - Logger.i("onRequestPermissionsResult:requestCode="+requestCode +" permissions=" + permissions[0]); + Logger.i("onRequestPermissionsResult:requestCode=" + requestCode + " permissions=" + permissions[0]); switch (requestCode) { case REQUEST_STORAGE_READ_ACCESS_PERMISSION: if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { - RxBus.getDefault().post(new RequestStorageReadAccessPermissionEvent(true)); + RxBus.getDefault().post(new RequestStorageReadAccessPermissionEvent(true, RequestStorageReadAccessPermissionEvent.TYPE_WRITE)); } else { finish(); } break; + case REQUEST_STORAGE_WRITE_ACCESS_PERMISSION: + if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { + RxBus.getDefault().post(new RequestStorageReadAccessPermissionEvent(true, RequestStorageReadAccessPermissionEvent.TYPE_WRITE)); + } else { + finish(); + } + break; + case REQUEST_CAMERA_ACCESS_PERMISSION: + if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { + RxBus.getDefault().post(new RequestStorageReadAccessPermissionEvent(true, RequestStorageReadAccessPermissionEvent.TYPE_CAMERA)); + } + break; default: super.onRequestPermissionsResult(requestCode, permissions, grantResults); } } + } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/adapter/BucketAdapter.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/adapter/BucketAdapter.java index baf2950a..31200c41 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/adapter/BucketAdapter.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/adapter/BucketAdapter.java @@ -1,10 +1,10 @@ package cn.finalteam.rxgalleryfinal.ui.adapter; -import android.content.Context; import android.content.res.ColorStateList; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; +import android.support.annotation.ColorInt; import android.support.v4.widget.CompoundButtonCompat; import android.support.v7.widget.AppCompatRadioButton; import android.support.v7.widget.RecyclerView; @@ -29,46 +29,45 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/7/4 下午5:40 */ -public class BucketAdapter extends RecyclerView.Adapter{ +public class BucketAdapter extends RecyclerView.Adapter { - private List mBucketList; - private Context mContext; - private LayoutInflater mInflater; - private Drawable mDefaultImage; - private Configuration mConfiguration; + private final List mBucketList; + private final Drawable mDefaultImage; + private final Configuration mConfiguration; private OnRecyclerViewItemClickListener mOnRecyclerViewItemClickListener; private BucketBean mSelectedBucket; - public BucketAdapter(Context context, List bucketList, Configuration configuration) { - this.mContext = context; + public BucketAdapter( + List bucketList, + Configuration configuration, + @ColorInt int color) { this.mBucketList = bucketList; this.mConfiguration = configuration; - this.mDefaultImage = new ColorDrawable(context.getResources().getColor(R.color.gallery_bucket_list_item_normal_color)); - this.mInflater = LayoutInflater.from(context); + this.mDefaultImage = new ColorDrawable(color); } @Override public BucketViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View view = mInflater.inflate(R.layout.gallery_adapter_bucket_item, parent, false); - return new BucketViewHolder(mContext, parent, view); + View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.gallery_adapter_bucket_item, parent, false); + return new BucketViewHolder(parent, view); } @Override public void onBindViewHolder(BucketViewHolder holder, int position) { BucketBean bucketBean = mBucketList.get(position); String bucketName = bucketBean.getBucketName(); - if(position != 0) { - SpannableString nameSpannable = new SpannableString(bucketName + "\n" + bucketBean.getImageCount() + this.mContext.getString(R.string.gallery_image_unit)); + if (position != 0) { + SpannableString nameSpannable = new SpannableString(bucketName + "\n" + bucketBean.getImageCount() + "张"); nameSpannable.setSpan(new ForegroundColorSpan(Color.GRAY), bucketName.length(), nameSpannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); nameSpannable.setSpan(new RelativeSizeSpan(0.8f), bucketName.length(), nameSpannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); holder.mTvBucketName.setText(nameSpannable); } else { holder.mTvBucketName.setText(bucketName); } - if(mSelectedBucket != null && TextUtils.equals(mSelectedBucket.getBucketId(), bucketBean.getBucketId())) { + if (mSelectedBucket != null && TextUtils.equals(mSelectedBucket.getBucketId(), bucketBean.getBucketId())) { holder.mRbSelected.setVisibility(View.VISIBLE); holder.mRbSelected.setChecked(true); } else { @@ -77,12 +76,13 @@ public void onBindViewHolder(BucketViewHolder holder, int position) { String path = bucketBean.getCover(); mConfiguration.getImageLoader() - .displayImage(mContext, path, holder.mIvBucketCover, mDefaultImage, mConfiguration.getImageConfig(), - true, 100, 100, bucketBean.getOrientation()); + .displayImage(holder.itemView.getContext(), path, holder.mIvBucketCover, mDefaultImage, mConfiguration.getImageConfig(), + true, mConfiguration.isPlayGif(), 100, 100, bucketBean.getOrientation()); } public void setSelectedBucket(BucketBean bucketBean) { this.mSelectedBucket = bucketBean; + notifyDataSetChanged(); } @Override @@ -94,15 +94,19 @@ public void setOnRecyclerViewItemClickListener(OnRecyclerViewItemClickListener l this.mOnRecyclerViewItemClickListener = listener; } - class BucketViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ + public interface OnRecyclerViewItemClickListener { + void onItemClick(View view, int position); + } + + class BucketViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { - TextView mTvBucketName; - SquareImageView mIvBucketCover; - AppCompatRadioButton mRbSelected; + final TextView mTvBucketName; + final SquareImageView mIvBucketCover; + final AppCompatRadioButton mRbSelected; - private ViewGroup mParentView; + private final ViewGroup mParentView; - public BucketViewHolder(Context context, ViewGroup parent, View itemView) { + BucketViewHolder(ViewGroup parent, View itemView) { super(itemView); this.mParentView = parent; mTvBucketName = (TextView) itemView.findViewById(R.id.tv_bucket_name); @@ -111,13 +115,13 @@ public BucketViewHolder(Context context, ViewGroup parent, View itemView) { itemView.setOnClickListener(this); - int checkTint = ThemeUtils.resolveColor(context, R.attr.gallery_checkbox_button_tint_color, R.color.gallery_default_checkbox_button_tint_color); + int checkTint = ThemeUtils.resolveColor(itemView.getContext(), R.attr.gallery_checkbox_button_tint_color, R.color.gallery_default_checkbox_button_tint_color); CompoundButtonCompat.setButtonTintList(mRbSelected, ColorStateList.valueOf(checkTint)); } @Override public void onClick(View v) { - if(mOnRecyclerViewItemClickListener != null) { + if (mOnRecyclerViewItemClickListener != null) { mOnRecyclerViewItemClickListener.onItemClick(v, getLayoutPosition()); } @@ -128,7 +132,6 @@ public void onClick(View v) { /** * 设置未所有Item为未选中 - * @param parentView */ private void setRadioDisChecked(ViewGroup parentView) { if (parentView == null || parentView.getChildCount() < 1) { @@ -138,15 +141,11 @@ private void setRadioDisChecked(ViewGroup parentView) { for (int i = 0; i < parentView.getChildCount(); i++) { View itemView = parentView.getChildAt(i); RadioButton rbSelect = (RadioButton) itemView.findViewById(R.id.rb_selected); - if(rbSelect!=null){ + if (rbSelect != null) { rbSelect.setVisibility(View.GONE); rbSelect.setChecked(false); } } } } - - public static interface OnRecyclerViewItemClickListener{ - void onItemClick(View view , int position); - } } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/adapter/MediaGridAdapter.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/adapter/MediaGridAdapter.java index 989ee2a0..fd6eb59d 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/adapter/MediaGridAdapter.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/adapter/MediaGridAdapter.java @@ -1,8 +1,8 @@ package cn.finalteam.rxgalleryfinal.ui.adapter; -import android.content.Context; import android.content.res.ColorStateList; import android.graphics.drawable.Drawable; +import android.support.v4.content.ContextCompat; import android.support.v4.widget.CompoundButtonCompat; import android.support.v7.widget.AppCompatCheckBox; import android.support.v7.widget.RecyclerView; @@ -10,10 +10,12 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.CompoundButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; -import android.widget.Toast; + +import com.facebook.drawee.view.SimpleDraweeView; import java.io.File; import java.util.List; @@ -21,98 +23,124 @@ import cn.finalteam.rxgalleryfinal.Configuration; import cn.finalteam.rxgalleryfinal.R; import cn.finalteam.rxgalleryfinal.bean.MediaBean; +import cn.finalteam.rxgalleryfinal.imageloader.FrescoImageLoader; import cn.finalteam.rxgalleryfinal.rxbus.RxBus; import cn.finalteam.rxgalleryfinal.rxbus.event.MediaCheckChangeEvent; import cn.finalteam.rxgalleryfinal.rxjob.Job; import cn.finalteam.rxgalleryfinal.rxjob.RxJob; import cn.finalteam.rxgalleryfinal.rxjob.job.ImageThmbnailJobCreate; import cn.finalteam.rxgalleryfinal.ui.activity.MediaActivity; -import cn.finalteam.rxgalleryfinal.ui.widget.RecyclerImageView; +import cn.finalteam.rxgalleryfinal.ui.base.IMultiImageCheckedListener; +import cn.finalteam.rxgalleryfinal.ui.widget.FixImageView; +import cn.finalteam.rxgalleryfinal.ui.widget.SquareRelativeLayout; +import cn.finalteam.rxgalleryfinal.utils.Logger; import cn.finalteam.rxgalleryfinal.utils.OsCompat; import cn.finalteam.rxgalleryfinal.utils.ThemeUtils; /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/5/18 下午7:48 */ public class MediaGridAdapter extends RecyclerView.Adapter { - private MediaActivity mMediaActivity; - private List mMediaBeanList; - private LayoutInflater mInflater; - private int mImageSize; - private Configuration mConfiguration; - private Drawable mDefaultImage; - private Drawable mImageViewBg; - private Drawable mCameraImage; - private int mCameraTextColor; - public MediaGridAdapter(MediaActivity mediaActivity, List list, int screenWidth, Configuration configuration) { + private static IMultiImageCheckedListener iMultiImageCheckedListener; + private final MediaActivity mMediaActivity; + private final List mMediaBeanList; + private final int mImageSize; + private final Configuration mConfiguration; + private final Drawable mDefaultImage; + private final Drawable mImageViewBg; + private final Drawable mCameraImage; + private final int mCameraImageBgColor; + private final int mCameraTextColor; + private int imageLoaderType = 0; + + public MediaGridAdapter( + MediaActivity mediaActivity, + List list, + int screenWidth, + Configuration configuration) { this.mMediaActivity = mediaActivity; this.mMediaBeanList = list; - this.mInflater = LayoutInflater.from(mediaActivity); - this.mImageSize = screenWidth/3; + this.mImageSize = screenWidth / 3; int defaultResId = ThemeUtils.resolveDrawableRes(mediaActivity, R.attr.gallery_default_image, R.drawable.gallery_default_image); - this.mDefaultImage = mediaActivity.getResources().getDrawable(defaultResId); + this.mDefaultImage = ContextCompat.getDrawable(mediaActivity, defaultResId); this.mConfiguration = configuration; + this.imageLoaderType = configuration.getImageLoaderType(); + this.mImageViewBg = ThemeUtils.resolveDrawable(mMediaActivity, R.attr.gallery_imageview_bg, R.drawable.gallery_default_image); + this.mCameraImage = ThemeUtils.resolveDrawable(mMediaActivity, R.attr.gallery_camera_image, R.drawable.gallery_ic_camera); + this.mCameraImageBgColor = ThemeUtils.resolveColor(mMediaActivity, R.attr.gallery_camera_bg, R.color.gallery_default_camera_bg_color); + this.mCameraTextColor = ThemeUtils.resolveColor(mMediaActivity, R.attr.gallery_take_image_text_color, R.color.gallery_default_take_image_text_color); + } - this.mImageViewBg = ThemeUtils.resolveDrawable(mMediaActivity, - R.attr.gallery_imageview_bg, R.drawable.gallery_default_image); - this.mCameraImage = ThemeUtils.resolveDrawable(mMediaActivity, R.attr.gallery_camera_bg, - R.drawable.gallery_ic_camera); - this.mCameraTextColor = ThemeUtils.resolveColor(mMediaActivity, R.attr.gallery_take_image_text_color, - R.color.gallery_default_take_image_text_color); + public static void setCheckedListener(IMultiImageCheckedListener checkedListener) { + iMultiImageCheckedListener = checkedListener; } @Override public GridViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View view = mInflater.inflate(R.layout.gallery_adapter_media_grid_item, parent, false); - return new GridViewHolder(mMediaActivity, view); + View view; + if (imageLoaderType != 3) { + view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_gallery_media_grid, parent, false); + } else { + view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_gallery_media_grid_fresco, parent, false); + } + return new GridViewHolder(view); } @Override public void onBindViewHolder(GridViewHolder holder, int position) { MediaBean mediaBean = mMediaBeanList.get(position); - if(mediaBean.getId() == Integer.MIN_VALUE) { + if (mediaBean.getId() == Integer.MIN_VALUE) { holder.mCbCheck.setVisibility(View.GONE); holder.mIvMediaImage.setVisibility(View.GONE); holder.mLlCamera.setVisibility(View.VISIBLE); holder.mIvCameraImage.setImageDrawable(mCameraImage); holder.mTvCameraTxt.setTextColor(mCameraTextColor); + holder.mTvCameraTxt.setText(mConfiguration.isImage() ? mMediaActivity.getString(R.string.gallery_take_image) : mMediaActivity.getString(R.string.gallery_video)); + holder.mIvCameraImage.setBackgroundColor(mCameraImageBgColor); } else { - if(mConfiguration.isRadio()) { + if (mConfiguration.isRadio()) { holder.mCbCheck.setVisibility(View.GONE); - } else{ + } else { holder.mCbCheck.setVisibility(View.VISIBLE); holder.mCbCheck.setOnClickListener(new OnCheckBoxClickListener(mediaBean)); + holder.mCbCheck.setOnCheckedChangeListener(new OnCheckBoxCheckListener(mediaBean)); } holder.mIvMediaImage.setVisibility(View.VISIBLE); holder.mLlCamera.setVisibility(View.GONE); - if(mMediaActivity.getCheckedList() != null && mMediaActivity.getCheckedList().contains(mediaBean)){ - holder.mCbCheck.setChecked(true); - } else { - holder.mCbCheck.setChecked(false); - } - String bitPath = mediaBean.getThumbnailSmallPath(); + holder.mCbCheck.setChecked(mMediaActivity.getCheckedList() != null && mMediaActivity.getCheckedList().contains(mediaBean)); + String bitPath = mediaBean.getThumbnailBigPath(); String smallPath = mediaBean.getThumbnailSmallPath(); - if(!new File(bitPath).exists() || !new File(smallPath).exists()) { + if (!new File(bitPath).exists() || !new File(smallPath).exists()) { Job job = new ImageThmbnailJobCreate(mMediaActivity, mediaBean).create(); RxJob.getDefault().addJob(job); } - String path = mediaBean.getThumbnailSmallPath(); - if(TextUtils.isEmpty(path)) { - path = mediaBean.getThumbnailBigPath(); - } - if(TextUtils.isEmpty(path)) { + String path; + if (mConfiguration.isPlayGif() && (imageLoaderType == 3 || imageLoaderType == 2)) { path = mediaBean.getOriginalPath(); + } else { + path = mediaBean.getThumbnailSmallPath(); + if (TextUtils.isEmpty(path)) { + path = mediaBean.getThumbnailBigPath(); + } + if (TextUtils.isEmpty(path)) { + path = mediaBean.getOriginalPath(); + } + } + Logger.w("提示path:" + path); + if (imageLoaderType != 3) { + OsCompat.setBackgroundDrawableCompat(holder.mIvMediaImage, mImageViewBg); + mConfiguration.getImageLoader() + .displayImage(mMediaActivity, path, (FixImageView) holder.mIvMediaImage, mDefaultImage, mConfiguration.getImageConfig(), + true, mConfiguration.isPlayGif(), mImageSize, mImageSize, mediaBean.getOrientation()); + } else { + OsCompat.setBackgroundDrawableCompat(holder.mIvMediaImage, mImageViewBg); + FrescoImageLoader.setImageSmall("file://" + path, (SimpleDraweeView) holder.mIvMediaImage, + mImageSize, mImageSize, holder.relativeLayout, mConfiguration.isPlayGif()); } - - OsCompat.setBackgroundDrawableCompat(holder.mIvMediaImage, mImageViewBg); - - mConfiguration.getImageLoader() - .displayImage(mMediaActivity, path, holder.mIvMediaImage, mDefaultImage, mConfiguration.getImageConfig(), - true, mImageSize, mImageSize, mediaBean.getOrientation()); } } @@ -121,49 +149,77 @@ public int getItemCount() { return mMediaBeanList.size(); } - class OnCheckBoxClickListener implements View.OnClickListener { - private MediaBean mediaBean; + static class GridViewHolder extends RecyclerView.ViewHolder { + + final AppCompatCheckBox mCbCheck; + final LinearLayout mLlCamera; + final TextView mTvCameraTxt; + final ImageView mIvCameraImage; + View mIvMediaImage; + SquareRelativeLayout relativeLayout; + - public OnCheckBoxClickListener(MediaBean bean) { + GridViewHolder(View itemView) { + super(itemView); + mIvMediaImage = itemView.findViewById(R.id.iv_media_image); + mCbCheck = (AppCompatCheckBox) itemView.findViewById(R.id.cb_check); + relativeLayout = (SquareRelativeLayout) itemView.findViewById(R.id.rootView); + mLlCamera = (LinearLayout) itemView.findViewById(R.id.ll_camera); + mTvCameraTxt = (TextView) itemView.findViewById(R.id.tv_camera_txt); + mIvCameraImage = (ImageView) itemView.findViewById(R.id.iv_camera_image); + + int checkTint = ThemeUtils.resolveColor(itemView.getContext(), R.attr.gallery_checkbox_button_tint_color, R.color.gallery_default_checkbox_button_tint_color); + CompoundButtonCompat.setButtonTintList(mCbCheck, ColorStateList.valueOf(checkTint)); + } + } + + private class OnCheckBoxClickListener implements View.OnClickListener { + + private final MediaBean mediaBean; + + OnCheckBoxClickListener(MediaBean bean) { this.mediaBean = bean; } @Override public void onClick(View view) { - if(mConfiguration.getMaxSize() == mMediaActivity.getCheckedList().size() && + if (mConfiguration.getMaxSize() == mMediaActivity.getCheckedList().size() && !mMediaActivity.getCheckedList().contains(mediaBean)) { AppCompatCheckBox checkBox = (AppCompatCheckBox) view; checkBox.setChecked(false); - Toast.makeText(mMediaActivity, mMediaActivity.getResources() - .getString(R.string.gallery_image_max_size_tip, mConfiguration.getMaxSize()), Toast.LENGTH_SHORT).show(); + Logger.i("=>" + mMediaActivity.getResources().getString(R.string.gallery_image_max_size_tip, mConfiguration.getMaxSize())); } else { RxBus.getDefault().post(new MediaCheckChangeEvent(mediaBean)); } } } - static class GridViewHolder extends RecyclerView.ViewHolder { + /** + * @author KARL-dujinyang + */ + private class OnCheckBoxCheckListener implements CompoundButton.OnCheckedChangeListener { + private final MediaBean mediaBean; - RecyclerImageView mIvMediaImage; - AppCompatCheckBox mCbCheck; - - LinearLayout mLlCamera; - TextView mTvCameraTxt; - ImageView mIvCameraImage; - - public GridViewHolder(Context context, View itemView) { - super(itemView); - mIvMediaImage = (RecyclerImageView) itemView.findViewById(R.id.iv_media_image); - mCbCheck = (AppCompatCheckBox) itemView.findViewById(R.id.cb_check); + OnCheckBoxCheckListener(MediaBean bean) { + this.mediaBean = bean; + } - mLlCamera = (LinearLayout) itemView.findViewById(R.id.ll_camera); - mTvCameraTxt = (TextView) itemView.findViewById(R.id.tv_camera_txt); - mIvCameraImage = (ImageView) itemView.findViewById(R.id.iv_camera_image); + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (mConfiguration.getMaxSize() == mMediaActivity.getCheckedList().size() && + !mMediaActivity.getCheckedList().contains(mediaBean)) { + AppCompatCheckBox checkBox = (AppCompatCheckBox) buttonView; + checkBox.setChecked(false); + Logger.i("选中:" + mMediaActivity.getResources().getString(R.string.gallery_image_max_size_tip, mConfiguration.getMaxSize())); + if (iMultiImageCheckedListener != null) { + iMultiImageCheckedListener.selectedImgMax(buttonView, isChecked, mConfiguration.getMaxSize()); + } + } else { + if (iMultiImageCheckedListener != null) + iMultiImageCheckedListener.selectedImg(buttonView, isChecked); + } - int checkTint = ThemeUtils.resolveColor(context, R.attr.gallery_checkbox_button_tint_color, R.color.gallery_default_checkbox_button_tint_color); - CompoundButtonCompat.setButtonTintList(mCbCheck, ColorStateList.valueOf(checkTint)); } } - } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/adapter/MediaPreviewAdapter.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/adapter/MediaPreviewAdapter.java index 3858dfa0..5dc09937 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/adapter/MediaPreviewAdapter.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/adapter/MediaPreviewAdapter.java @@ -1,9 +1,7 @@ package cn.finalteam.rxgalleryfinal.ui.adapter; -import android.content.Context; import android.graphics.drawable.Drawable; import android.text.TextUtils; -import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -12,52 +10,54 @@ import cn.finalteam.rxgalleryfinal.Configuration; import cn.finalteam.rxgalleryfinal.R; import cn.finalteam.rxgalleryfinal.bean.MediaBean; -import cn.finalteam.rxgalleryfinal.utils.ThemeUtils; import uk.co.senab.photoview.PhotoView; /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/7/21 下午10:12 */ public class MediaPreviewAdapter extends RecyclingPagerAdapter { - private Context mContext; - private LayoutInflater mInflater; - private List mMediaList; - private Configuration mConfiguration; - private Drawable mDefaultImage; - private int mScreenWidth, mScreenHeight; - private int mPageColor; + private final List mMediaList; + private final Configuration mConfiguration; + private final Drawable mDefaultImage; + private final int mScreenWidth; + private final int mScreenHeight; + private final int mPageColor; - public MediaPreviewAdapter(Context context, List list, int screenWidth, int screenHeight, Configuration configuration) { - this.mContext = context; - this.mInflater = LayoutInflater.from(context); + public MediaPreviewAdapter(List list, + int screenWidth, + int screenHeight, + Configuration configuration, + int pageColor, + Drawable drawable) { this.mMediaList = list; this.mScreenWidth = screenWidth; this.mScreenHeight = screenHeight; this.mConfiguration = configuration; - this.mPageColor = ThemeUtils.resolveColor(context, R.attr.gallery_page_bg, R.color.gallery_default_page_bg); - int defaultResId = ThemeUtils.resolveDrawableRes(context, R.attr.gallery_default_image, R.drawable.gallery_default_image); - this.mDefaultImage = context.getResources().getDrawable(defaultResId); + this.mPageColor = pageColor; + this.mDefaultImage = drawable; } @Override public View getView(int position, View convertView, ViewGroup container) { MediaBean mediaBean = mMediaList.get(position); - View view = mInflater.inflate(R.layout.gallery_media_image_preview_item, null); - PhotoView ivImage = (PhotoView) view.findViewById(R.id.iv_media_image); + if (convertView == null) { + convertView = View.inflate(container.getContext(), R.layout.gallery_media_image_preview_item, null); + } + PhotoView ivImage = (PhotoView) convertView.findViewById(R.id.iv_media_image); String path = null; - if(mediaBean.getWidth() > 1200 || mediaBean.getHeight() > 1200){ + if (mediaBean.getWidth() > 1200 || mediaBean.getHeight() > 1200) { path = mediaBean.getThumbnailBigPath(); } - if(TextUtils.isEmpty(path)) { + if (TextUtils.isEmpty(path)) { path = mediaBean.getOriginalPath(); } ivImage.setBackgroundColor(mPageColor); - mConfiguration.getImageLoader().displayImage(mContext, path, ivImage,mDefaultImage, mConfiguration.getImageConfig(), - false, mScreenWidth, mScreenHeight, mediaBean.getOrientation()); - return view; + mConfiguration.getImageLoader().displayImage(container.getContext(), path, ivImage, mDefaultImage, mConfiguration.getImageConfig(), + false, mConfiguration.isPlayGif(), mScreenWidth, mScreenHeight, mediaBean.getOrientation()); + return convertView; } @Override diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/base/IMultiImageCheckedListener.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/base/IMultiImageCheckedListener.java new file mode 100644 index 00000000..9ed79b5f --- /dev/null +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/base/IMultiImageCheckedListener.java @@ -0,0 +1,11 @@ +package cn.finalteam.rxgalleryfinal.ui.base; + +/** + * 复选 + * Created by KARL on 2017-03-17 04-22-30. + */ +public interface IMultiImageCheckedListener { + void selectedImg(Object t, boolean isChecked); + + void selectedImgMax(Object t, boolean isChecked, int maxSize); +} diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/base/IRadioImageCheckedListener.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/base/IRadioImageCheckedListener.java new file mode 100644 index 00000000..642c96e2 --- /dev/null +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/base/IRadioImageCheckedListener.java @@ -0,0 +1,18 @@ +package cn.finalteam.rxgalleryfinal.ui.base; + +/** + * 单选裁剪 + * Created by KARL on 2017-05-31. + */ +public interface IRadioImageCheckedListener { + + /** + * 裁剪之后 + */ + void cropAfter(Object t); + + /** + * 返回true则关闭,false默认不关闭 + */ + boolean isActivityFinish(); +} diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaGridFragment.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaGridFragment.java index ed121220..8bc9494f 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaGridFragment.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaGridFragment.java @@ -1,13 +1,16 @@ package cn.finalteam.rxgalleryfinal.ui.fragment; import android.app.Activity; +import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; import android.support.annotation.Nullable; +import android.support.v4.content.ContextCompat; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; @@ -21,6 +24,7 @@ import com.yalantis.ucrop.UCrop; import com.yalantis.ucrop.UCropActivity; +import com.yalantis.ucrop.model.AspectRatio; import java.io.File; import java.text.SimpleDateFormat; @@ -28,6 +32,7 @@ import java.util.Date; import java.util.List; import java.util.Locale; +import java.util.Random; import cn.finalteam.rxgalleryfinal.Configuration; import cn.finalteam.rxgalleryfinal.R; @@ -39,18 +44,17 @@ import cn.finalteam.rxgalleryfinal.bean.MediaBean; import cn.finalteam.rxgalleryfinal.presenter.impl.MediaGridPresenterImpl; import cn.finalteam.rxgalleryfinal.rxbus.RxBus; -import cn.finalteam.rxgalleryfinal.rxbus.RxBusSubscriber; -import cn.finalteam.rxgalleryfinal.rxbus.event.BaseResultEvent; +import cn.finalteam.rxgalleryfinal.rxbus.RxBusDisposable; import cn.finalteam.rxgalleryfinal.rxbus.event.CloseMediaViewPageFragmentEvent; -import cn.finalteam.rxgalleryfinal.rxbus.event.ImageMultipleResultEvent; import cn.finalteam.rxgalleryfinal.rxbus.event.ImageRadioResultEvent; import cn.finalteam.rxgalleryfinal.rxbus.event.MediaCheckChangeEvent; +import cn.finalteam.rxgalleryfinal.rxbus.event.OpenMediaPageFragmentEvent; import cn.finalteam.rxgalleryfinal.rxbus.event.OpenMediaPreviewFragmentEvent; import cn.finalteam.rxgalleryfinal.rxbus.event.RequestStorageReadAccessPermissionEvent; -import cn.finalteam.rxgalleryfinal.rxbus.event.OpenMediaPageFragmentEvent; import cn.finalteam.rxgalleryfinal.ui.activity.MediaActivity; import cn.finalteam.rxgalleryfinal.ui.adapter.BucketAdapter; import cn.finalteam.rxgalleryfinal.ui.adapter.MediaGridAdapter; +import cn.finalteam.rxgalleryfinal.ui.base.IRadioImageCheckedListener; import cn.finalteam.rxgalleryfinal.ui.widget.FooterAdapter; import cn.finalteam.rxgalleryfinal.ui.widget.HorizontalDividerItemDecoration; import cn.finalteam.rxgalleryfinal.ui.widget.MarginDecoration; @@ -58,36 +62,50 @@ import cn.finalteam.rxgalleryfinal.utils.CameraUtils; import cn.finalteam.rxgalleryfinal.utils.DeviceUtils; import cn.finalteam.rxgalleryfinal.utils.EmptyViewUtils; +import cn.finalteam.rxgalleryfinal.utils.FileUtils; import cn.finalteam.rxgalleryfinal.utils.Logger; import cn.finalteam.rxgalleryfinal.utils.MediaScanner; import cn.finalteam.rxgalleryfinal.utils.MediaUtils; import cn.finalteam.rxgalleryfinal.utils.PermissionCheckUtils; +import cn.finalteam.rxgalleryfinal.utils.SimpleDateUtils; import cn.finalteam.rxgalleryfinal.utils.ThemeUtils; import cn.finalteam.rxgalleryfinal.view.MediaGridView; -import rx.Observable; -import rx.Observer; -import rx.Subscription; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; +import io.reactivex.Observable; +import io.reactivex.ObservableOnSubscribe; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.observers.DisposableObserver; +import io.reactivex.schedulers.Schedulers; /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/5/7 上午10:02 + *

+ * Desction: 直接暴漏 + * Author:KARL-Dujinyang + * Date:2017. */ public class MediaGridFragment extends BaseFragment implements MediaGridView, RecyclerViewFinal.OnLoadMoreListener, - FooterAdapter.OnItemClickListener,View.OnClickListener, MediaScanner.ScanCallback, BucketAdapter.OnRecyclerViewItemClickListener { - + FooterAdapter.OnItemClickListener, View.OnClickListener, MediaScanner.ScanCallback, BucketAdapter.OnRecyclerViewItemClickListener { + + private static final String IMAGE_TYPE = "image/jpeg"; + //接口-单选-是否裁剪 + public static IRadioImageCheckedListener iListenerRadio; + //预留公开命名接口 + private static File mImageStoreDir; + private static File mImageStoreCropDir; //裁剪目录 + //裁剪后+name + private static File mCropPath = null; private final String IMAGE_STORE_FILE_NAME = "IMG_%s.jpg"; + private final String VIDEO_STORE_FILE_NAME = "IMG_%s.mp4"; private final int TAKE_IMAGE_REQUEST_CODE = 1001; + private final int CROP_IMAGE_REQUEST_CODE = 1011; private final String TAKE_URL_STORAGE_KEY = "take_url_storage_key"; private final String BUCKET_ID_KEY = "bucket_id_key"; - private final int LIMIT = 23; - MediaGridPresenterImpl mMediaGridPresenter; DisplayMetrics mScreenSize; - private List mMediaBeanList; private MediaGridAdapter mMediaGridAdapter; private RecyclerViewFinal mRvMedia; @@ -99,39 +117,125 @@ public class MediaGridFragment extends BaseFragment implements MediaGridView, Re private TextView mTvFolderName; private TextView mTvPreview; private RelativeLayout mRlRootView; - + //扫描 private MediaScanner mMediaScanner; - private int mPage = 1; - private File mImageStoreDir; private String mImagePath; private String mBucketId = String.valueOf(Integer.MIN_VALUE); private MediaActivity mMediaActivity; - private Subscription mSubscrMediaCheckChangeEvent; - private Subscription mSubscrCloseMediaViewPageFragmentEvent; - private Subscription mSubscrRequestStorageReadAccessPermissionEvent; - private static boolean openCameraOnStart = false; - private static boolean returnAfterShot = false; + private Disposable mMediaCheckChangeDisposable; + private Disposable mCloseMediaViewPageFragmentDisposable; + private Disposable mRequestStorageReadAccessPermissionDisposable; + + private SlideInUnderneathAnimation slideInUnderneathAnimation; + private SlideOutUnderneathAnimation slideOutUnderneathAnimation; + + private int uCropStatusColor; + private int uCropToolbarColor; + private int uCropActivityWidgetColor; + private int uCropToolbarWidgetColor; + private String uCropTitle; + private String requestStorageAccessPermissionTips; + public static MediaGridFragment newInstance(Configuration configuration) { MediaGridFragment fragment = new MediaGridFragment(); Bundle bundle = new Bundle(); bundle.putParcelable(EXTRA_CONFIGURATION, configuration); fragment.setArguments(bundle); - openCameraOnStart = configuration.isOpenCameraOnStart(); - returnAfterShot = configuration.isReturnAfterShot(); return fragment; } + /** + * getImageStoreDir + * + * @return 存储路径 + */ + public static File getImageStoreDirByFile() { + return mImageStoreDir; + } + + /** + * getImageStoreDir + * + * @return 存储路径 + */ + public static String getImageStoreDirByStr() { + if (mImageStoreDir != null) + return mImageStoreDir.getPath(); + else + return null; + } + + /** + * 设置路径 + */ + public static void setImageStoreDir(File imgFile) { + Logger.i("设置图片保存路径为:" + imgFile.getAbsolutePath()); + mImageStoreDir = imgFile; + } + + /** + * 设置路径 + */ + public static void setImageStoreDir(String imgFile) { + mImageStoreDir = new File(Environment.getExternalStorageDirectory(), "/DCIM" + File.separator + imgFile + File.separator); + Logger.i("设置图片保存路径为:" + mImageStoreDir.getAbsolutePath()); + } + + /** + * getImageStoreDir裁剪 + * + * @return 裁剪存储路径 + */ + public static File getImageStoreCropDirByFile() { + return mImageStoreCropDir; + } + + /** + * getImageStoreDir + * + * @return 存储路径 + */ + public static String getImageStoreCropDirByStr() { + if (mImageStoreCropDir != null) + return mImageStoreCropDir.getPath(); + else + return null; + } + + /** + * 设置裁剪路径 + */ + public static void setImageStoreCropDir(File imgFile) { + mImageStoreCropDir = imgFile; + Logger.i("设置图片裁剪保存路径为:" + mImageStoreCropDir.getAbsolutePath()); + } + + /** + * 设置裁剪路径 + * + * @param imgFile 裁剪 + */ + public static void setImageStoreCropDir(String imgFile) { + mImageStoreCropDir = new File(Environment.getExternalStorageDirectory(), "/DCIM" + File.separator + imgFile + File.separator); + if (!mImageStoreCropDir.exists()) { + mImageStoreCropDir.mkdirs(); + } + Logger.i("设置图片裁剪保存路径为:" + mImageStoreCropDir.getAbsolutePath()); + } + + public static void setRadioListener(IRadioImageCheckedListener radioListener) { + MediaGridFragment.iListenerRadio = radioListener; + } + @Override public void onAttach(Context context) { super.onAttach(context); - if(context instanceof MediaActivity) { + if (context instanceof MediaActivity) { mMediaActivity = (MediaActivity) context; } - //临时目录 - mImageStoreDir = new File(Environment.getExternalStorageDirectory(), "/DCIM/RxGalleryFinal/"); mMediaScanner = new MediaScanner(context); } @@ -142,6 +246,7 @@ public int getContentView() { @Override public void onViewCreatedOk(View view, @Nullable Bundle savedInstanceState) { + mRvMedia = (RecyclerViewFinal) view.findViewById(R.id.rv_media); mLlEmptyView = (LinearLayout) view.findViewById(R.id.ll_empty_view); mRvBucket = (RecyclerView) view.findViewById(R.id.rv_bucket); @@ -161,15 +266,23 @@ public void onViewCreatedOk(View view, @Nullable Bundle savedInstanceState) { mTvPreview = (TextView) view.findViewById(R.id.tv_preview); mTvPreview.setOnClickListener(this); mTvPreview.setEnabled(false); - if(mConfiguration.isRadio()){ + if (mConfiguration.isRadio()) { view.findViewById(R.id.tv_preview_vr).setVisibility(View.GONE); mTvPreview.setVisibility(View.GONE); + + } else { + if (mConfiguration.isHidePreview()) { + view.findViewById(R.id.tv_preview_vr).setVisibility(View.GONE); + mTvPreview.setVisibility(View.GONE); + } else { + view.findViewById(R.id.tv_preview_vr).setVisibility(View.VISIBLE); + mTvPreview.setVisibility(View.VISIBLE); + } } mMediaBeanList = new ArrayList<>(); mScreenSize = DeviceUtils.getScreenSize(getContext()); - mMediaGridAdapter = new MediaGridAdapter(mMediaActivity, mMediaBeanList, - mScreenSize.widthPixels, mConfiguration); + mMediaGridAdapter = new MediaGridAdapter(mMediaActivity, mMediaBeanList, mScreenSize.widthPixels, mConfiguration); mRvMedia.setAdapter(mMediaGridAdapter); mMediaGridPresenter = new MediaGridPresenterImpl(getContext(), mConfiguration.isImage()); mMediaGridPresenter.setMediaGridView(this); @@ -184,40 +297,56 @@ public void onViewCreatedOk(View view, @Nullable Bundle savedInstanceState) { .build()); mRvBucket.setLayoutManager(linearLayoutManager); mBucketBeanList = new ArrayList<>(); - mBucketAdapter = new BucketAdapter(getContext(), mBucketBeanList, mConfiguration); + mBucketAdapter = new BucketAdapter(mBucketBeanList, mConfiguration, ContextCompat.getColor(getContext(), R.color.gallery_bucket_list_item_normal_color)); mRvBucket.setAdapter(mBucketAdapter); mRvMedia.setOnItemClickListener(this); mMediaGridPresenter.getBucketList(); mBucketAdapter.setOnRecyclerViewItemClickListener(this); mRlBucektOverview.setVisibility(View.INVISIBLE); - new SlideInUnderneathAnimation(mRvBucket) + + if (slideInUnderneathAnimation == null) { + slideInUnderneathAnimation = new SlideInUnderneathAnimation(mRvBucket); + } + + slideInUnderneathAnimation .setDirection(Animation.DIRECTION_DOWN) .animate(); subscribeEvent(); Activity activity = mMediaActivity; - if(activity == null){ + if (activity == null) { activity = getActivity(); } + if (mConfiguration.isImage()) { + mTvFolderName.setText(R.string.gallery_all_image); + } else { + mTvFolderName.setText(R.string.gallery_all_video); + } + String requestStorageAccessPermissionTips = ThemeUtils.resolveString(getContext(), R.attr.gallery_request_storage_access_permission_tips, R.string.gallery_default_request_storage_access_permission_tips); boolean success = PermissionCheckUtils.checkReadExternalPermission(activity, requestStorageAccessPermissionTips, MediaActivity.REQUEST_STORAGE_READ_ACCESS_PERMISSION); - if(success) { + if (success) { mMediaGridPresenter.getMediaList(mBucketId, mPage, LIMIT); } + + } + /** + * RxBus + */ private void subscribeEvent() { - mSubscrMediaCheckChangeEvent = RxBus.getDefault().toObservable(MediaCheckChangeEvent.class) - .subscribe(new RxBusSubscriber() { + mMediaCheckChangeDisposable = RxBus.getDefault().toObservable(MediaCheckChangeEvent.class) + .subscribeWith(new RxBusDisposable() { @Override protected void onEvent(MediaCheckChangeEvent mediaCheckChangeEvent) { - if(mMediaActivity.getCheckedList().size() == 0){ + if (mMediaActivity.getCheckedList().size() == 0) { mTvPreview.setEnabled(false); } else { mTvPreview.setEnabled(true); @@ -225,46 +354,68 @@ protected void onEvent(MediaCheckChangeEvent mediaCheckChangeEvent) { } }); - RxBus.getDefault().add(mSubscrMediaCheckChangeEvent); + RxBus.getDefault().add(mMediaCheckChangeDisposable); - mSubscrCloseMediaViewPageFragmentEvent = RxBus.getDefault().toObservable(CloseMediaViewPageFragmentEvent.class) - .subscribe(new RxBusSubscriber() { + mCloseMediaViewPageFragmentDisposable = RxBus.getDefault().toObservable(CloseMediaViewPageFragmentEvent.class) + .subscribeWith(new RxBusDisposable() { @Override protected void onEvent(CloseMediaViewPageFragmentEvent closeMediaViewPageFragmentEvent) throws Exception { mMediaGridAdapter.notifyDataSetChanged(); } }); - RxBus.getDefault().add(mSubscrCloseMediaViewPageFragmentEvent); + RxBus.getDefault().add(mCloseMediaViewPageFragmentDisposable); - mSubscrRequestStorageReadAccessPermissionEvent = RxBus.getDefault().toObservable(RequestStorageReadAccessPermissionEvent.class) - .subscribe(new RxBusSubscriber() { + mRequestStorageReadAccessPermissionDisposable = RxBus.getDefault().toObservable(RequestStorageReadAccessPermissionEvent.class) + .subscribeWith(new RxBusDisposable() { @Override protected void onEvent(RequestStorageReadAccessPermissionEvent requestStorageReadAccessPermissionEvent) throws Exception { - if(requestStorageReadAccessPermissionEvent.isSuccess()){ - mMediaGridPresenter.getMediaList(mBucketId, mPage, LIMIT); + if (requestStorageReadAccessPermissionEvent.getType() == RequestStorageReadAccessPermissionEvent.TYPE_WRITE) { + if (requestStorageReadAccessPermissionEvent.isSuccess()) { + mMediaGridPresenter.getMediaList(mBucketId, mPage, LIMIT); + } else { + getActivity().finish(); + } } else { - getActivity().finish(); + if (requestStorageReadAccessPermissionEvent.isSuccess()) { + openCamera(mMediaActivity); + } } } }); - RxBus.getDefault().add(mSubscrRequestStorageReadAccessPermissionEvent); + RxBus.getDefault().add(mRequestStorageReadAccessPermissionDisposable); } + /** + * 设置主题 + */ @Override public void setTheme() { super.setTheme(); + uCropStatusColor = ThemeUtils.resolveColor(getActivity(), R.attr.gallery_ucrop_status_bar_color, R.color.gallery_default_ucrop_color_widget_active); + uCropToolbarColor = ThemeUtils.resolveColor(getActivity(), R.attr.gallery_ucrop_toolbar_color, R.color.gallery_default_ucrop_color_widget_active); + uCropActivityWidgetColor = ThemeUtils.resolveColor(getActivity(), R.attr.gallery_ucrop_activity_widget_color, R.color.gallery_default_ucrop_color_widget); + uCropToolbarWidgetColor = ThemeUtils.resolveColor(getActivity(), R.attr.gallery_ucrop_toolbar_widget_color, R.color.gallery_default_toolbar_widget_color); + uCropTitle = ThemeUtils.resolveString(getActivity(), R.attr.gallery_ucrop_toolbar_title, R.string.gallery_title_cut); int pageColor = ThemeUtils.resolveColor(getContext(), R.attr.gallery_page_bg, R.color.gallery_default_page_bg); mRlRootView.setBackgroundColor(pageColor); + requestStorageAccessPermissionTips = ThemeUtils.resolveString(getContext(), R.attr.gallery_request_camera_permission_tips, R.string.gallery_default_camera_access_permission_tips); } @Override protected void onFirstTimeLaunched() { - if(openCameraOnStart){ - this.openCameraOnStart(); - } + } + @Override + public void onStart() { + super.onStart(); + onLoadFile(); + //直接刷新一次 + // refreshUI(); + } + + @Override public void loadMore() { mMediaGridPresenter.getMediaList(mBucketId, mPage, LIMIT); @@ -272,7 +423,7 @@ public void loadMore() { @Override public void onRequestMediaCallback(List list) { - if(!mConfiguration.isHideCamera()) { + if (!mConfiguration.isHideCamera()) { if (mPage == 1 && TextUtils.equals(mBucketId, String.valueOf(Integer.MIN_VALUE))) { MediaBean takePhotoBean = new MediaBean(); takePhotoBean.setId(Integer.MIN_VALUE); @@ -308,13 +459,12 @@ public void onRequestMediaCallback(List list) { @Override public void onRequestBucketCallback(List list) { - if(list == null || list.size() == 0){ + if (list == null || list.size() == 0) { return; } mBucketBeanList.addAll(list); mBucketAdapter.setSelectedBucket(list.get(0)); - mBucketAdapter.notifyDataSetChanged(); } @Override @@ -322,7 +472,7 @@ public void onItemClick(View view, int position) { BucketBean bucketBean = mBucketBeanList.get(position); String bucketId = bucketBean.getBucketId(); mRlBucektOverview.setVisibility(View.GONE); - if(TextUtils.equals(mBucketId, bucketId)){ + if (TextUtils.equals(mBucketId, bucketId)) { return; } mBucketId = bucketId; @@ -330,8 +480,8 @@ public void onItemClick(View view, int position) { mRvMedia.setHasLoadMore(false); mMediaBeanList.clear(); mMediaGridAdapter.notifyDataSetChanged(); + mTvFolderName.setText(bucketBean.getBucketName()); mBucketAdapter.setSelectedBucket(bucketBean); - mRvMedia.setFooterViewHide(true); mPage = 1; mMediaGridPresenter.getMediaList(mBucketId, mPage, LIMIT); @@ -339,6 +489,10 @@ public void onItemClick(View view, int position) { @Override public void onItemClick(RecyclerView.ViewHolder holder, int position) { + onObItemClick(position); + } + + public void onObItemClick(int position) { MediaBean mediaBean = mMediaBeanList.get(position); if (mediaBean.getId() == Integer.MIN_VALUE) { @@ -347,17 +501,23 @@ public void onItemClick(RecyclerView.ViewHolder holder, int position) { return; } - openCamera(); - + boolean b = PermissionCheckUtils.checkCameraPermission(mMediaActivity, requestStorageAccessPermissionTips, MediaActivity.REQUEST_CAMERA_ACCESS_PERMISSION); + if (b) { + openCamera(mMediaActivity); + } } else { if (mConfiguration.isRadio()) { - radioNext(mediaBean); + if (mConfiguration.isImage()) { + radioNext(mediaBean); + } else { + videoRadioNext(mediaBean); + } } else { MediaBean firstBean = mMediaBeanList.get(0); ArrayList gridMediaList = new ArrayList<>(); gridMediaList.addAll(mMediaBeanList); int pos = position; - if(firstBean.getId() == Integer.MIN_VALUE) { + if (firstBean.getId() == Integer.MIN_VALUE) { pos = position - 1; gridMediaList.clear(); List list = mMediaBeanList.subList(1, mMediaBeanList.size()); @@ -368,20 +528,74 @@ public void onItemClick(RecyclerView.ViewHolder holder, int position) { } } + /** + * 处理 Video 选择 是否预览 + * + * @param mediaBean + */ + private void videoRadioNext(MediaBean mediaBean) { + if (!mConfiguration.isVideoPreview()) { + setPostMediaBean(mediaBean); + getActivity().finish(); + return; + } + try { + Intent openVideo = new Intent(Intent.ACTION_VIEW); + openVideo.setDataAndType(Uri.parse(mediaBean.getOriginalPath()), "video/*"); + startActivity(openVideo); + } catch (Exception e) { + Toast.makeText(getContext(), "启动播放器失败", Toast.LENGTH_SHORT).show(); + } + } + + /** + * 处理回调 + */ + private void setPostMediaBean(MediaBean mediaBean) { + ImageCropBean bean = new ImageCropBean(); + bean.copyMediaBean(mediaBean); + RxBus.getDefault().post(new ImageRadioResultEvent(bean)); + } + + /** + * 区分功能 + */ private void radioNext(MediaBean mediaBean) { - if(!mConfiguration.isCrop()){ - ImageCropBean bean = new ImageCropBean(); - bean.copyMediaBean(mediaBean); - RxBus.getDefault().post(new ImageRadioResultEvent(bean)); + Logger.i("isCrop :" + mConfiguration.isCrop()); + if (!mConfiguration.isCrop()) { + setPostMediaBean(mediaBean); getActivity().finish(); } else { + //裁剪根据大家需求加上选择完图片后的回调 + setPostMediaBean(mediaBean); String originalPath = mediaBean.getOriginalPath(); File file = new File(originalPath); - Uri outUri = Uri.fromFile(new File(mImageStoreDir, file.getName())); + Random random = new Random(); + String outName = String.format(IMAGE_STORE_FILE_NAME, SimpleDateUtils.getNowTime() + "_" + random.nextInt(1024)); + Logger.i("--->isCrop:" + mImageStoreCropDir); + Logger.i("--->mediaBean.getOriginalPath():" + mediaBean.getOriginalPath()); + mCropPath = new File(mImageStoreCropDir, outName); + Uri outUri = Uri.fromFile(mCropPath); + if (!mImageStoreCropDir.exists()) { + mImageStoreCropDir.mkdirs(); + } + if (!file.exists()) { + file.mkdirs(); + } + Uri inputUri = Uri.fromFile(new File(mediaBean.getOriginalPath())); Intent intent = new Intent(getContext(), UCropActivity.class); + + + // UCrop 参数 start Bundle bundle = new Bundle(); + bundle.putParcelable(UCrop.EXTRA_OUTPUT_URI, outUri); bundle.putParcelable(UCrop.Options.EXTRA_ASPECT_RATIO_OPTIONS, mediaBean); + bundle.putInt(UCrop.Options.EXTRA_STATUS_BAR_COLOR, uCropStatusColor); + bundle.putInt(UCrop.Options.EXTRA_TOOL_BAR_COLOR, uCropToolbarColor); + bundle.putString(UCrop.Options.EXTRA_UCROP_TITLE_TEXT_TOOLBAR, uCropTitle); + bundle.putInt(UCrop.Options.EXTRA_UCROP_COLOR_WIDGET_ACTIVE, uCropActivityWidgetColor); + bundle.putInt(UCrop.Options.EXTRA_UCROP_WIDGET_COLOR_TOOLBAR, uCropToolbarWidgetColor); bundle.putBoolean(UCrop.Options.EXTRA_HIDE_BOTTOM_CONTROLS, mConfiguration.isHideBottomControls()); bundle.putIntArray(UCrop.Options.EXTRA_ALLOWED_GESTURES, mConfiguration.getAllowedGestures()); bundle.putInt(UCrop.Options.EXTRA_COMPRESSION_QUALITY, mConfiguration.getCompressionQuality()); @@ -393,31 +607,60 @@ private void radioNext(MediaBean mediaBean) { bundle.putInt(UCrop.EXTRA_MAX_SIZE_Y, mConfiguration.getMaxResultHeight()); bundle.putInt(UCrop.Options.EXTRA_ASPECT_RATIO_SELECTED_BY_DEFAULT, mConfiguration.getSelectedByDefault()); bundle.putBoolean(UCrop.Options.EXTRA_FREE_STYLE_CROP, mConfiguration.isFreestyleCropEnabled()); + bundle.putParcelable(UCrop.EXTRA_INPUT_URI, inputUri); + // UCrop 参数 end + + int bk = FileUtils.existImageDir(inputUri.getPath()); + Logger.i("--->" + inputUri.getPath()); + Logger.i("--->" + outUri.getPath()); + ArrayList aspectRatioList = new ArrayList<>(); + AspectRatio[] aspectRatios = mConfiguration.getAspectRatio(); + if (aspectRatios != null) { + for (int i = 0; i < aspectRatios.length; i++) { + aspectRatioList.add(i, aspectRatios[i]); + Logger.i("自定义比例=>" + aspectRatioList.get(i).getAspectRatioX() + " " + aspectRatioList.get(i).getAspectRatioY()); + } + } + // AspectRatio[]aspectRatios = mConfiguration.getAspectRatio(); + bundle.putParcelableArrayList(UCrop.Options.EXTRA_ASPECT_RATIO_OPTIONS, aspectRatioList);//EXTRA_CONFIGURATION intent.putExtras(bundle); - startActivity(intent); + if (bk != -1) { + //裁剪 + startActivityForResult(intent, CROP_IMAGE_REQUEST_CODE); + } else { + Logger.w("点击图片无效"); + } } } - private void openCamera() { - Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); - if (captureIntent.resolveActivity(getActivity().getPackageManager()) != null) { - SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA); - String filename = String.format(IMAGE_STORE_FILE_NAME, dateFormat.format(new Date())); - mImagePath = new File(mImageStoreDir, filename).getAbsolutePath(); - captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(mImagePath))); - startActivityForResult(captureIntent, TAKE_IMAGE_REQUEST_CODE); - } else { - Toast.makeText(getContext(), R.string.gallery_device_camera_unable, Toast.LENGTH_SHORT).show(); - } - } + public void openCamera(Context context) { + + + boolean image = mConfiguration.isImage(); - public void openCameraOnStart(){ - if (!CameraUtils.hasCamera(getContext())) { - Toast.makeText(getContext(), R.string.gallery_device_no_camera_tips, Toast.LENGTH_SHORT).show(); + Intent captureIntent = image ? new Intent(MediaStore.ACTION_IMAGE_CAPTURE) : new Intent(MediaStore.ACTION_VIDEO_CAPTURE); + if (captureIntent.resolveActivity(context.getPackageManager()) == null) { + Toast.makeText(getContext(), R.string.gallery_device_camera_unable, Toast.LENGTH_SHORT).show(); return; } - openCamera(); + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA); + String filename = String.format(image ? IMAGE_STORE_FILE_NAME : VIDEO_STORE_FILE_NAME, dateFormat.format(new Date())); + Logger.i("openCamera:" + mImageStoreDir.getAbsolutePath()); + File fileImagePath = new File(mImageStoreDir, filename); + mImagePath = fileImagePath.getAbsolutePath(); + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { + captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(fileImagePath)); + } else { + ContentValues contentValues = new ContentValues(1); + contentValues.put(MediaStore.Images.Media.DATA, mImagePath); + Uri uri = getContext().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues); + captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri); + } + // video : 1: 高质量 0 低质量 +// captureIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1); + startActivityForResult(captureIntent, TAKE_IMAGE_REQUEST_CODE); } @Override @@ -426,9 +669,40 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { Logger.i("onActivityResult: requestCode=" + requestCode + ", resultCode=" + resultCode); if (requestCode == TAKE_IMAGE_REQUEST_CODE && resultCode == Activity.RESULT_OK) { Logger.i(String.format("拍照成功,图片存储路径:%s", mImagePath)); + mMediaScanner.scanFile(mImagePath, mConfiguration.isImage() ? IMAGE_TYPE : "", this); + } else if (requestCode == 222) { + Toast.makeText(getActivity(), "摄像成功", Toast.LENGTH_SHORT).show(); + } else if (requestCode == CROP_IMAGE_REQUEST_CODE && data != null) { + Logger.i("裁剪成功"); + refreshUI(); + onCropFinished(); + } + } - //刷新相册数据库 - mMediaScanner.scanFile(mImagePath, "image/jpeg", this); + /** + * 裁剪之后 + * setResult(RESULT_OK, new Intent() + * .putExtra(UCrop.EXTRA_OUTPUT_URI, uri) + * .putExtra(UCrop.EXTRA_OUTPUT_CROP_ASPECT_RATIO, resultAspectRatio) + * .putExtra(UCrop.EXTRA_OUTPUT_IMAGE_WIDTH, imageWidth) + * .putExtra(UCrop.EXTRA_OUTPUT_IMAGE_HEIGHT, imageHeight) + */ + private void onCropFinished() { + if (iListenerRadio != null && mCropPath != null) { + if (mConfiguration.isCrop()) { + iListenerRadio.cropAfter(mCropPath); + } + } else { + Logger.i("# CropPath is null!# "); + } + //裁剪默认会关掉这个界面. 实现接口返回true则不关闭. + if (iListenerRadio == null) { + getActivity().finish(); + } else { + boolean flag = iListenerRadio.isActivityFinish(); + Logger.i("# crop image is flag # :" + flag); + if (flag) + getActivity().finish(); } } @@ -438,7 +712,7 @@ public void onSaveInstanceState(Bundle outState) { if (!TextUtils.isEmpty(mImagePath)) { outState.putString(TAKE_URL_STORAGE_KEY, mImagePath); } - if(!TextUtils.isEmpty(mBucketId)) { + if (!TextUtils.isEmpty(mBucketId)) { outState.putString(BUCKET_ID_KEY, mBucketId); } } @@ -448,6 +722,9 @@ protected void onRestoreState(Bundle savedInstanceState) { } + + //**************************************************************************** + @Override protected void onSaveState(Bundle outState) { @@ -472,81 +749,137 @@ public void onDestroy() { @Override public void onClick(View v) { int id = v.getId(); - if(id == R.id.tv_preview) { + if (id == R.id.tv_preview) { RxBus.getDefault().post(new OpenMediaPreviewFragmentEvent()); - } else if(id == R.id.tv_folder_name) { + } else if (id == R.id.tv_folder_name) { v.setEnabled(false); - int visibility = mRlBucektOverview.getVisibility(); - if(visibility == View.VISIBLE) { - new SlideOutUnderneathAnimation(mRvBucket) - .setDirection(Animation.DIRECTION_DOWN) - .setDuration(Animation.DURATION_DEFAULT) - .setListener(animation -> { - v.setEnabled(true); - mRlBucektOverview.setVisibility(View.GONE); - }) - .animate(); - } else { - mRlBucektOverview.setVisibility(View.VISIBLE); - new SlideInUnderneathAnimation(mRvBucket) - .setDirection(Animation.DIRECTION_DOWN) - .setDuration(Animation.DURATION_DEFAULT) - .setListener(animation -> { - v.setEnabled(true); - }) - .animate(); + if (isShowRvBucketView()) { + hideRvBucketView(); + } else { + showRvBucketView(); } } } + public boolean isShowRvBucketView() { + return mRlBucektOverview != null && mRlBucektOverview.getVisibility() == View.VISIBLE; + } + + + public void showRvBucketView() { + if (mRlBucektOverview == null) { + slideInUnderneathAnimation = new SlideInUnderneathAnimation(mRlBucektOverview); + } + mRlBucektOverview.setVisibility(View.VISIBLE); + slideInUnderneathAnimation + .setDirection(Animation.DIRECTION_DOWN) + .setDuration(Animation.DURATION_DEFAULT) + .setListener(animation -> mTvFolderName.setEnabled(true)) + .animate(); + } + + public void hideRvBucketView() { + if (slideOutUnderneathAnimation == null) { + slideOutUnderneathAnimation = new SlideOutUnderneathAnimation(mRvBucket); + } + slideOutUnderneathAnimation + .setDirection(Animation.DIRECTION_DOWN) + .setDuration(Animation.DURATION_DEFAULT) + .setListener(animation -> { + mTvFolderName.setEnabled(true); + mRlBucektOverview.setVisibility(View.GONE); + }) + .animate(); + } + + /** + * Observable刷新图库 + */ + public void refreshUI() { + try { + Logger.i("->getImageStoreDirByFile().getPath().toString():" + getImageStoreDirByFile().getPath()); + Logger.i("->getImageStoreCropDirByStr ().toString():" + getImageStoreCropDirByStr()); + if (!TextUtils.isEmpty(mImagePath)) + mMediaScanner.scanFile(mImagePath, IMAGE_TYPE, this); + if (mCropPath != null) { + Logger.i("->mCropPath:" + mCropPath.getPath() + " " + IMAGE_TYPE); + mMediaScanner.scanFile(mCropPath.getPath(), IMAGE_TYPE, this); + } + } catch (Exception e) { + Logger.e(e.getMessage()); + } + } + @Override public void onScanCompleted(String[] images) { - if(images == null || images.length == 0){ + if (images == null || images.length == 0) { Logger.i("images empty"); return; } - Observable.create((Observable.OnSubscribe) subscriber -> { - MediaBean mediaBean = MediaUtils.getMediaBeanWithImage(getContext(), images[0]); + // mediaBean 有可能为Null,onNext 做了处理,在 getMediaBeanWithImage 时候就不处理Null了 + Observable.create((ObservableOnSubscribe) subscriber -> { + MediaBean mediaBean = + mConfiguration.isImage() ? MediaUtils.getMediaBeanWithImage(getContext(), images[0]) + : + MediaUtils.getMediaBeanWithVideo(getContext(), images[0]); subscriber.onNext(mediaBean); - subscriber.onCompleted(); + subscriber.onComplete(); }) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Observer() { - @Override - public void onCompleted() { - } - - @Override - public void onError(Throwable e) { - Logger.i("获取MediaBean异常"); - } + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new DisposableObserver() { + @Override + public void onComplete() { + } - @Override - public void onNext(MediaBean mediaBean) { - - if(!isDetached() && mediaBean != null) { - if(returnAfterShot){ - ArrayList list = new ArrayList<>(); - list.add(mediaBean); - BaseResultEvent event = new ImageMultipleResultEvent(list); - RxBus.getDefault().post(event); - getActivity().finish(); - }else{ - mMediaBeanList.add(1, mediaBean); - mMediaGridAdapter.notifyDataSetChanged(); + @Override + public void onError(Throwable e) { + Logger.i("获取MediaBean异常" + e.toString()); } - } - } - }); + @Override + public void onNext(MediaBean mediaBean) { + if (!isDetached() && mediaBean != null) { + int bk = FileUtils.existImageDir(mediaBean.getOriginalPath()); + if (bk != -1) { + mMediaBeanList.add(1, mediaBean); + mMediaGridAdapter.notifyDataSetChanged(); + } else { + Logger.i("获取:无"); + } + } + + } + }); } @Override public void onDestroyView() { super.onDestroyView(); - RxBus.getDefault().remove(mSubscrMediaCheckChangeEvent); - RxBus.getDefault().remove(mSubscrCloseMediaViewPageFragmentEvent); + RxBus.getDefault().remove(mMediaCheckChangeDisposable); + RxBus.getDefault().remove(mCloseMediaViewPageFragmentDisposable); + + } + + /** + * onAttach 转 onStart + */ + public void onLoadFile() { + //没有的话就默认路径 + if (getImageStoreDirByFile() == null && getImageStoreDirByStr() == null) { + mImageStoreDir = new File(Environment.getExternalStorageDirectory(), "/DCIM/IMMQY/"); + setImageStoreCropDir(mImageStoreDir); + } + if (!mImageStoreDir.exists()) { + mImageStoreDir.mkdirs(); + } + if (getImageStoreCropDirByFile() == null && getImageStoreCropDirByStr() == null) { + mImageStoreCropDir = new File(mImageStoreDir, "crop"); + if (!mImageStoreCropDir.exists()) { + mImageStoreCropDir.mkdirs(); + } + setImageStoreCropDir(mImageStoreCropDir); + } } } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaPageFragment.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaPageFragment.java index bf2e5388..cf6a3a94 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaPageFragment.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaPageFragment.java @@ -4,6 +4,7 @@ import android.content.res.ColorStateList; import android.os.Bundle; import android.support.annotation.Nullable; +import android.support.v4.content.ContextCompat; import android.support.v4.view.ViewPager; import android.support.v4.widget.CompoundButtonCompat; import android.support.v7.widget.AppCompatCheckBox; @@ -31,14 +32,14 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/5/14 下午10:02 */ public class MediaPageFragment extends BaseFragment implements ViewPager.OnPageChangeListener, - View.OnClickListener{ + View.OnClickListener { private static final String EXTRA_MEDIA_LIST = EXTRA_PREFIX + ".MediaList"; - private static final String EXTRA_ITEM_CLICK_POSITION = EXTRA_PREFIX +".ItemClickPosition"; + private static final String EXTRA_ITEM_CLICK_POSITION = EXTRA_PREFIX + ".ItemClickPosition"; DisplayMetrics mScreenSize; @@ -51,15 +52,7 @@ public class MediaPageFragment extends BaseFragment implements ViewPager.OnPageC private MediaActivity mMediaActivity; private int mItemClickPosition; - @Override - public void onAttach(Context context) { - super.onAttach(context); - if(context instanceof MediaActivity) { - mMediaActivity = (MediaActivity) context; - } - } - - public static MediaPageFragment newInstance(Configuration configuration, ArrayList list, int position){ + public static MediaPageFragment newInstance(Configuration configuration, ArrayList list, int position) { MediaPageFragment fragment = new MediaPageFragment(); Bundle bundle = new Bundle(); bundle.putParcelable(EXTRA_CONFIGURATION, configuration); @@ -69,6 +62,14 @@ public static MediaPageFragment newInstance(Configuration configuration, ArrayLi return fragment; } + @Override + public void onAttach(Context context) { + super.onAttach(context); + if (context instanceof MediaActivity) { + mMediaActivity = (MediaActivity) context; + } + } + @Override public int getContentView() { return R.layout.gallery_fragment_media_page; @@ -82,16 +83,18 @@ public void onViewCreatedOk(View view, @Nullable Bundle savedInstanceState) { mScreenSize = DeviceUtils.getScreenSize(getContext()); mMediaBeanList = new ArrayList<>(); - if(savedInstanceState != null){ + if (savedInstanceState != null) { List mediaList = savedInstanceState.getParcelableArrayList(EXTRA_MEDIA_LIST); mItemClickPosition = savedInstanceState.getInt(EXTRA_ITEM_CLICK_POSITION); - if(mediaList != null) { + if (mediaList != null) { mMediaBeanList.addAll(mediaList); } } - mMediaPreviewAdapter = new MediaPreviewAdapter(getContext(), mMediaBeanList, - mScreenSize.widthPixels, mScreenSize.heightPixels, mConfiguration); + mMediaPreviewAdapter = new MediaPreviewAdapter(mMediaBeanList, + mScreenSize.widthPixels, mScreenSize.heightPixels, mConfiguration + , ThemeUtils.resolveColor(getActivity(), R.attr.gallery_page_bg, R.color.gallery_default_page_bg), + ContextCompat.getDrawable(getActivity(), ThemeUtils.resolveDrawableRes(getActivity(), R.attr.gallery_default_image, R.drawable.gallery_default_image))); mViewPager.setAdapter(mMediaPreviewAdapter); mCbCheck.setOnClickListener(this); mViewPager.setCurrentItem(mItemClickPosition); @@ -102,13 +105,13 @@ public void onViewCreatedOk(View view, @Nullable Bundle savedInstanceState) { @Override public void onStart() { super.onStart(); - if(mConfiguration == null || mMediaBeanList.size() == 0 + if (mConfiguration == null || mMediaBeanList.size() == 0 || mCbCheck == null || mViewPager == null) { return; } MediaBean mediaBean = mMediaBeanList.get(mItemClickPosition); - if(mMediaActivity != null && mMediaActivity.getCheckedList() != null){ - if(mMediaActivity.getCheckedList().contains(mediaBean)) { + if (mMediaActivity != null && mMediaActivity.getCheckedList() != null) { + if (mMediaActivity.getCheckedList().contains(mediaBean)) { mCbCheck.setChecked(true); } } @@ -133,19 +136,15 @@ protected void onFirstTimeLaunched() { @Override protected void onRestoreState(Bundle savedInstanceState) { - if(savedInstanceState==null){ + if (savedInstanceState == null) { return; } - List mediaList = savedInstanceState.getParcelableArrayList(EXTRA_MEDIA_LIST); mItemClickPosition = savedInstanceState.getInt(EXTRA_ITEM_CLICK_POSITION); - - if(mediaList != null) { + if (mediaList != null) { mMediaBeanList.clear(); - Logger.i("恢复数据:" + mediaList.size() +" d=" + mediaList.get(0).getOriginalPath()); + Logger.i("恢复数据:" + mediaList.size() + " d=" + mediaList.get(0).getOriginalPath()); mMediaBeanList.addAll(mediaList); - } else{ - Logger.i("恢复数据: null"); } mViewPager.setCurrentItem(mItemClickPosition); mMediaPreviewAdapter.notifyDataSetChanged(); @@ -153,7 +152,7 @@ protected void onRestoreState(Bundle savedInstanceState) { @Override protected void onSaveState(Bundle outState) { - if(outState==null){ + if (outState == null) { return; } outState.putParcelableArrayList(EXTRA_MEDIA_LIST, mMediaBeanList); @@ -170,7 +169,7 @@ public void onPageSelected(int position) { MediaBean mediaBean = mMediaBeanList.get(position); //判断是否选择 - if(mMediaActivity != null && mMediaActivity.getCheckedList() != null){ + if (mMediaActivity != null && mMediaActivity.getCheckedList() != null) { mCbCheck.setChecked(mMediaActivity.getCheckedList().contains(mediaBean)); } else { mCbCheck.setChecked(false); @@ -185,17 +184,16 @@ public void onPageScrollStateChanged(int state) { /** * 改变选择 - * @param view */ @Override public void onClick(View view) { - if(mMediaBeanList.size() == 0){ + if (mMediaBeanList.size() == 0) { return; } int position = mViewPager.getCurrentItem(); MediaBean mediaBean = mMediaBeanList.get(position); - if(mConfiguration.getMaxSize() == mMediaActivity.getCheckedList().size() + if (mConfiguration.getMaxSize() == mMediaActivity.getCheckedList().size() && !mMediaActivity.getCheckedList().contains(mediaBean)) { Toast.makeText(getContext(), getResources() .getString(R.string.gallery_image_max_size_tip, mConfiguration.getMaxSize()), Toast.LENGTH_SHORT).show(); diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaPreviewFragment.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaPreviewFragment.java index 3af5a4a8..b9abaa90 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaPreviewFragment.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaPreviewFragment.java @@ -4,6 +4,7 @@ import android.content.res.ColorStateList; import android.os.Bundle; import android.support.annotation.Nullable; +import android.support.v4.content.ContextCompat; import android.support.v4.view.ViewPager; import android.support.v4.widget.CompoundButtonCompat; import android.support.v7.widget.AppCompatCheckBox; @@ -29,11 +30,11 @@ /** * Desction:图片预览 - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/6/9 上午1:35 */ public class MediaPreviewFragment extends BaseFragment implements ViewPager.OnPageChangeListener, - View.OnClickListener{ + View.OnClickListener { private static final String EXTRA_PAGE_INDEX = EXTRA_PREFIX + ".PageIndex"; @@ -41,22 +42,13 @@ public class MediaPreviewFragment extends BaseFragment implements ViewPager.OnPa private AppCompatCheckBox mCbCheck; private ViewPager mViewPager; - private MediaPreviewAdapter mMediaPreviewAdapter; private List mMediaBeanList; private RelativeLayout mRlRootView; private MediaActivity mMediaActivity; private int mPagerPosition; - @Override - public void onAttach(Context context) { - super.onAttach(context); - if(context instanceof MediaActivity) { - mMediaActivity = (MediaActivity) context; - } - } - - public static MediaPreviewFragment newInstance(Configuration configuration, int position){ + public static MediaPreviewFragment newInstance(Configuration configuration, int position) { MediaPreviewFragment fragment = new MediaPreviewFragment(); Bundle bundle = new Bundle(); bundle.putParcelable(EXTRA_CONFIGURATION, configuration); @@ -65,6 +57,14 @@ public static MediaPreviewFragment newInstance(Configuration configuration, int return fragment; } + @Override + public void onAttach(Context context) { + super.onAttach(context); + if (context instanceof MediaActivity) { + mMediaActivity = (MediaActivity) context; + } + } + @Override public int getContentView() { return R.layout.gallery_fragment_media_preview; @@ -78,15 +78,17 @@ public void onViewCreatedOk(View view, @Nullable Bundle savedInstanceState) { mRlRootView = (RelativeLayout) view.findViewById(R.id.rl_root_view); mScreenSize = DeviceUtils.getScreenSize(getContext()); mMediaBeanList = new ArrayList<>(); - if(mMediaActivity.getCheckedList() != null){ + if (mMediaActivity.getCheckedList() != null) { mMediaBeanList.addAll(mMediaActivity.getCheckedList()); } - mMediaPreviewAdapter = new MediaPreviewAdapter(getContext(), mMediaBeanList, - mScreenSize.widthPixels, mScreenSize.heightPixels, mConfiguration); + MediaPreviewAdapter mMediaPreviewAdapter = new MediaPreviewAdapter(mMediaBeanList, + mScreenSize.widthPixels, mScreenSize.heightPixels, mConfiguration, + ThemeUtils.resolveColor(getActivity(), R.attr.gallery_page_bg, R.color.gallery_default_page_bg), + ContextCompat.getDrawable(getActivity(), ThemeUtils.resolveDrawableRes(getActivity(), R.attr.gallery_default_image, R.drawable.gallery_default_image))); mViewPager.setAdapter(mMediaPreviewAdapter); mCbCheck.setOnClickListener(this); - if(savedInstanceState != null) { + if (savedInstanceState != null) { mPagerPosition = savedInstanceState.getInt(EXTRA_PAGE_INDEX); } } @@ -96,6 +98,8 @@ public void onStart() { super.onStart(); mViewPager.setCurrentItem(mPagerPosition, false); mViewPager.addOnPageChangeListener(this); + //#ADD UI预览数量的BUG + RxBus.getDefault().post(new MediaViewPagerChangedEvent(mPagerPosition, mMediaBeanList.size(), true)); } @Override @@ -117,14 +121,14 @@ protected void onFirstTimeLaunched() { @Override protected void onRestoreState(Bundle savedInstanceState) { - if(savedInstanceState != null){ + if (savedInstanceState != null) { mPagerPosition = savedInstanceState.getInt(EXTRA_PAGE_INDEX); } } @Override protected void onSaveState(Bundle outState) { - if(outState != null){ + if (outState != null) { outState.putInt(EXTRA_PAGE_INDEX, mPagerPosition); } } @@ -139,7 +143,7 @@ public void onPageSelected(int position) { MediaBean mediaBean = mMediaBeanList.get(position); mCbCheck.setChecked(false); //判断是否选择 - if(mMediaActivity != null && mMediaActivity.getCheckedList() != null){ + if (mMediaActivity != null && mMediaActivity.getCheckedList() != null) { mCbCheck.setChecked(mMediaActivity.getCheckedList().contains(mediaBean)); } @@ -152,13 +156,12 @@ public void onPageScrollStateChanged(int state) { /** * 改变选择 - * @param view */ @Override public void onClick(View view) { int position = mViewPager.getCurrentItem(); MediaBean mediaBean = mMediaBeanList.get(position); - if(mConfiguration.getMaxSize() == mMediaActivity.getCheckedList().size() + if (mConfiguration.getMaxSize() == mMediaActivity.getCheckedList().size() && !mMediaActivity.getCheckedList().contains(mediaBean)) { Toast.makeText(getContext(), getResources() .getString(R.string.gallery_image_max_size_tip, mConfiguration.getMaxSize()), Toast.LENGTH_SHORT).show(); diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/FileUtils.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/FileUtils.java index d7bd79b8..b4ebbd80 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/FileUtils.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/FileUtils.java @@ -2,9 +2,14 @@ /** * Desction:文件工具类 - * Author:pengjianbo - * Date:16/5/6 下午5:45 + * Author:dujinyang */ public class FileUtils { + /** + * 验证是否是图片路径 + */ + public static int existImageDir(String dir) { + return dir.trim().lastIndexOf("."); + } } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaUtils.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaUtils.java index f49f7e18..11b414d2 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaUtils.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaUtils.java @@ -3,10 +3,11 @@ import android.content.ContentResolver; import android.content.Context; import android.database.Cursor; -import android.media.ExifInterface; import android.net.Uri; import android.os.Build; import android.provider.MediaStore; +import android.support.annotation.Nullable; +import android.support.media.ExifInterface; import android.text.TextUtils; import java.io.File; @@ -20,7 +21,7 @@ /** * Desction:媒体获取工具 - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/5/4 下午4:11 */ public class MediaUtils { @@ -28,16 +29,12 @@ public class MediaUtils { public static List getMediaWithImageList(Context context, int page, int limit) { return getMediaWithImageList(context, String.valueOf(Integer.MIN_VALUE), page, limit); } + /** * 从数据库中读取图片 - * @param context - * @param bucketId - * @param page - * @param limit - * @return */ public static List getMediaWithImageList(Context context, String bucketId, int page, int limit) { - int offset = (page -1) * limit; + int offset = (page - 1) * limit; List mediaBeanList = new ArrayList<>(); ContentResolver contentResolver = context.getContentResolver(); List projection = new ArrayList<>(); @@ -53,34 +50,35 @@ public static List getMediaWithImageList(Context context, String buck projection.add(MediaStore.Images.Media.LONGITUDE); projection.add(MediaStore.Images.Media.ORIENTATION); projection.add(MediaStore.Images.Media.SIZE); - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { projection.add(MediaStore.Images.Media.WIDTH); projection.add(MediaStore.Images.Media.HEIGHT); } String selection = null; - String []selectionArgs = null; - if(!TextUtils.equals(bucketId, String.valueOf(Integer.MIN_VALUE))) { + String[] selectionArgs = null; + if (!TextUtils.equals(bucketId, String.valueOf(Integer.MIN_VALUE))) { selection = MediaStore.Images.Media.BUCKET_ID + "=?"; selectionArgs = new String[]{bucketId}; } Cursor cursor = contentResolver.query( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection.toArray(new String[projection.size()]), selection, - selectionArgs, MediaStore.Images.Media.DATE_ADDED +" DESC LIMIT " + limit +" OFFSET " + offset); - if(cursor != null) { + selectionArgs, MediaStore.Images.Media.DATE_ADDED + " DESC LIMIT " + limit + " OFFSET " + offset); + if (cursor != null) { int count = cursor.getCount(); - if(count > 0) { + if (count > 0) { cursor.moveToFirst(); do { MediaBean mediaBean = parseImageCursorAndCreateThumImage(context, cursor); - mediaBeanList.add(mediaBean); + if (mediaBean != null) { + mediaBeanList.add(mediaBean); + } } while (cursor.moveToNext()); } } - if(cursor != null && !cursor.isClosed()){ + if (cursor != null && !cursor.isClosed()) { cursor.close(); } - cursor = null; return mediaBeanList; } @@ -90,14 +88,9 @@ public static List getMediaWithVideoList(Context context, int page, i /** * 从数据库中读取视频 - * @param context - * @param bucketId - * @param page - * @param limit - * @return */ public static List getMediaWithVideoList(Context context, String bucketId, int page, int limit) { - int offset = (page -1) * limit; + int offset = (page - 1) * limit; List mediaBeanList = new ArrayList<>(); ContentResolver contentResolver = context.getContentResolver(); List projection = new ArrayList<>(); @@ -112,23 +105,23 @@ public static List getMediaWithVideoList(Context context, String buck projection.add(MediaStore.Video.Media.LATITUDE); projection.add(MediaStore.Video.Media.LONGITUDE); projection.add(MediaStore.Video.Media.SIZE); - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { projection.add(MediaStore.Video.Media.WIDTH); projection.add(MediaStore.Video.Media.HEIGHT); } String selection = null; - String []selectionArgs = null; - if(!TextUtils.equals(bucketId, String.valueOf(Integer.MIN_VALUE))) { + String[] selectionArgs = null; + if (!TextUtils.equals(bucketId, String.valueOf(Integer.MIN_VALUE))) { selection = MediaStore.Video.Media.BUCKET_ID + "=?"; selectionArgs = new String[]{bucketId}; } Cursor cursor = contentResolver.query( MediaStore.Video.Media.EXTERNAL_CONTENT_URI, projection.toArray(new String[projection.size()]), selection, - selectionArgs, MediaStore.Video.Media.DATE_ADDED +" DESC LIMIT " + limit +" OFFSET " + offset); - if(cursor != null) { + selectionArgs, MediaStore.Video.Media.DATE_ADDED + " DESC LIMIT " + limit + " OFFSET " + offset); + if (cursor != null) { int count = cursor.getCount(); - if(count > 0) { + if (count > 0) { cursor.moveToFirst(); do { MediaBean mediaBean = parseVideoCursorAndCreateThumImage(context, cursor); @@ -137,18 +130,14 @@ public static List getMediaWithVideoList(Context context, String buck } } - if(cursor != null && !cursor.isClosed()){ + if (cursor != null && !cursor.isClosed()) { cursor.close(); } - cursor = null; return mediaBeanList; } /** * 根据原图获取图片相关信息 - * @param context - * @param originalPath - * @return */ public static MediaBean getMediaBeanWithImage(Context context, String originalPath) { ContentResolver contentResolver = context.getContentResolver(); @@ -165,54 +154,98 @@ public static MediaBean getMediaBeanWithImage(Context context, String originalPa projection.add(MediaStore.Images.Media.LONGITUDE); projection.add(MediaStore.Images.Media.ORIENTATION); projection.add(MediaStore.Images.Media.SIZE); - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { projection.add(MediaStore.Images.Media.WIDTH); projection.add(MediaStore.Images.Media.HEIGHT); } Cursor cursor = contentResolver.query( - MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection.toArray(new String[projection.size()]), MediaStore.Images.Media.DATA +"=?", + MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection.toArray(new String[projection.size()]), MediaStore.Images.Media.DATA + "=?", new String[]{originalPath}, null); MediaBean mediaBean = null; - if(cursor != null && cursor.getCount() > 0) { + if (cursor != null && cursor.getCount() > 0) { cursor.moveToFirst(); - mediaBean = parseImageCursorAndCreateThumImage(context, cursor); + mediaBean = parseImageCursorAndCreateThumImage(context, cursor); } - if(cursor != null && !cursor.isClosed()){ + if (cursor != null && !cursor.isClosed()) { + cursor.close(); + } + return mediaBean; + } + + /** + * 根据地址获取视频相关信息 + */ + public static MediaBean getMediaBeanWithVideo(Context context, String originalPath) { + ContentResolver contentResolver = context.getContentResolver(); + List projection = new ArrayList<>(); + projection.add(MediaStore.Video.Media._ID); + projection.add(MediaStore.Video.Media.TITLE); + projection.add(MediaStore.Video.Media.DATA); + projection.add(MediaStore.Video.Media.BUCKET_ID); + projection.add(MediaStore.Video.Media.BUCKET_DISPLAY_NAME); + projection.add(MediaStore.Video.Media.MIME_TYPE); + projection.add(MediaStore.Video.Media.DATE_ADDED); + projection.add(MediaStore.Video.Media.DATE_MODIFIED); + projection.add(MediaStore.Video.Media.LATITUDE); + projection.add(MediaStore.Video.Media.LONGITUDE); + projection.add(MediaStore.Video.Media.SIZE); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + projection.add(MediaStore.Video.Media.WIDTH); + projection.add(MediaStore.Video.Media.HEIGHT); + } + Cursor cursor = contentResolver.query( + MediaStore.Video.Media.EXTERNAL_CONTENT_URI, + projection.toArray(new String[projection.size()]), + MediaStore.Images.Media.DATA + "=?", + new String[]{originalPath}, null); + MediaBean mediaBean = null; + if (cursor != null && cursor.getCount() > 0) { + cursor.moveToFirst(); + mediaBean = parseVideoCursorAndCreateThumImage(context, cursor); + } + if (cursor != null && !cursor.isClosed()) { cursor.close(); } - cursor = null; return mediaBean; } /** * 解析图片cursor并且创建缩略图 - * @param context - * @param cursor - * @return + *

+ * update 17.07.23 log + *

+ * 判断图片 Size ,如果小于等于0则返回 Null,避免出现 No such file or directory */ + @Nullable private static MediaBean parseImageCursorAndCreateThumImage(Context context, Cursor cursor) { - MediaBean mediaBean = new MediaBean(); + long size = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media.SIZE)); + String originalPath = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA)); + if (TextUtils.isEmpty(originalPath) || size <= 0 || !new File(originalPath).exists()) { + return null; + } + long id = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media._ID)); - mediaBean.setId(id); String title = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.TITLE)); + String bucketId = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_ID)); + String bucketDisplayName = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME)); + String mimeType = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.MIME_TYPE)); + long createDate = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media.DATE_ADDED)); + long modifiedDate = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media.DATE_MODIFIED)); + + MediaBean mediaBean = new MediaBean(); + mediaBean.setId(id); mediaBean.setTitle(title); - String originalPath = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA)); mediaBean.setOriginalPath(originalPath); - String bucketId = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_ID)); mediaBean.setBucketId(bucketId); - String bucketDisplayName = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME)); mediaBean.setBucketDisplayName(bucketDisplayName); - String mimeType = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.MIME_TYPE)); mediaBean.setMimeType(mimeType); - long createDate = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media.DATE_ADDED)); mediaBean.setCreateDate(createDate); - long modifiedDate = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media.DATE_MODIFIED)); mediaBean.setModifiedDate(modifiedDate); mediaBean.setThumbnailBigPath(createThumbnailBigFileName(context, originalPath).getAbsolutePath()); mediaBean.setThumbnailSmallPath(createThumbnailSmallFileName(context, originalPath).getAbsolutePath()); int width = 0, height = 0; - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { width = cursor.getInt(cursor.getColumnIndex(MediaStore.Images.Media.WIDTH)); height = cursor.getInt(cursor.getColumnIndex(MediaStore.Images.Media.HEIGHT)); } else { @@ -240,9 +273,6 @@ private static MediaBean parseImageCursorAndCreateThumImage(Context context, Cur /** * 解析视频cursor并且创建缩略图 - * @param context - * @param cursor - * @return */ private static MediaBean parseVideoCursorAndCreateThumImage(Context context, Cursor cursor) { MediaBean mediaBean = new MediaBean(); @@ -270,7 +300,7 @@ private static MediaBean parseVideoCursorAndCreateThumImage(Context context, Cur mediaBean.setThumbnailSmallPath(createThumbnailSmallFileName(context, originalPath).getAbsolutePath()); int width = 0, height = 0; - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { width = cursor.getInt(cursor.getColumnIndex(MediaStore.Video.Media.WIDTH)); height = cursor.getInt(cursor.getColumnIndex(MediaStore.Video.Media.HEIGHT)); } else { @@ -294,20 +324,16 @@ private static MediaBean parseVideoCursorAndCreateThumImage(Context context, Cur public static File createThumbnailBigFileName(Context context, String originalPath) { File storeFile = StorageUtils.getCacheDirectory(context); - File bigThumFile = new File(storeFile, "big_" + FilenameUtils.getName(originalPath)); - return bigThumFile; + return new File(storeFile, "big_" + FilenameUtils.getName(originalPath)); } public static File createThumbnailSmallFileName(Context context, String originalPath) { File storeFile = StorageUtils.getCacheDirectory(context); - File smallThumFile = new File(storeFile, "small_" + FilenameUtils.getName(originalPath)); - return smallThumFile; + return new File(storeFile, "small_" + FilenameUtils.getName(originalPath)); } /** * 获取所有的图片文件夹 - * @param context - * @return */ public static List getAllBucketByImage(Context context) { return getAllBucket(context, true); @@ -315,8 +341,6 @@ public static List getAllBucketByImage(Context context) { /** * 获取所以视频文件夹 - * @param context - * @return */ public static List getAllBucketByVideo(Context context) { return getAllBucket(context, false); @@ -324,23 +348,20 @@ public static List getAllBucketByVideo(Context context) { /** * 获取所有的问media文件夹 - * @param context - * @param isImage - * @return */ public static List getAllBucket(Context context, boolean isImage) { List bucketBeenList = new ArrayList<>(); ContentResolver contentResolver = context.getContentResolver(); String[] projection; - if(isImage){ - projection = new String[] { + if (isImage) { + projection = new String[]{ MediaStore.Images.Media.BUCKET_ID, MediaStore.Images.Media.DATA, MediaStore.Images.Media.BUCKET_DISPLAY_NAME, MediaStore.Images.Media.ORIENTATION, }; } else { - projection = new String[] { + projection = new String[]{ MediaStore.Video.Media.BUCKET_ID, MediaStore.Video.Media.DATA, MediaStore.Video.Media.BUCKET_DISPLAY_NAME, @@ -349,7 +370,7 @@ public static List getAllBucket(Context context, boolean isImage) { BucketBean allMediaBucket = new BucketBean(); allMediaBucket.setBucketId(String.valueOf(Integer.MIN_VALUE)); Uri uri; - if(isImage) { + if (isImage) { allMediaBucket.setBucketName(context.getString(R.string.gallery_all_image)); uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; } else { @@ -359,25 +380,22 @@ public static List getAllBucket(Context context, boolean isImage) { bucketBeenList.add(allMediaBucket); Cursor cursor = null; try { - cursor = contentResolver.query(uri, projection, null, null, MediaStore.Video.Media.DATE_ADDED + " DESC"); - } catch (Exception e){ + cursor = contentResolver.query(uri, projection, null, null, MediaStore.Video.Media.DATE_ADDED + " DESC"); + } catch (Exception e) { Logger.e(e); } - if(cursor != null && cursor.getCount() > 0) { + if (cursor != null && cursor.getCount() > 0) { cursor.moveToFirst(); do { BucketBean bucketBean = new BucketBean(); String bucketId; String bucketKey; String cover; - if(isImage) { + if (isImage) { bucketId = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_ID)); bucketBean.setBucketId(bucketId); String bucketDisplayName = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME)); - if("RxGalleryFinal".equals(bucketDisplayName)){ - continue; - } bucketBean.setBucketName(bucketDisplayName); bucketKey = MediaStore.Images.Media.BUCKET_ID; cover = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA)); @@ -391,33 +409,28 @@ public static List getAllBucket(Context context, boolean isImage) { bucketKey = MediaStore.Video.Media.BUCKET_ID; cover = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DATA)); } - if(TextUtils.isEmpty(allMediaBucket.getCover())) { + if (TextUtils.isEmpty(allMediaBucket.getCover())) { allMediaBucket.setCover(cover); } - if(bucketBeenList.contains(bucketBean)) { - bucketBean = null; - bucketId = null; - bucketKey = null; - continue; + if (bucketBeenList.contains(bucketBean)) { + continue; } //获取数量 - Cursor c = contentResolver.query(uri, projection, bucketKey +"=?", new String[]{bucketId}, null); - if(c != null && c.getCount() > 0) { + Cursor c = contentResolver.query(uri, projection, bucketKey + "=?", new String[]{bucketId}, null); + if (c != null && c.getCount() > 0) { bucketBean.setImageCount(c.getCount()); } bucketBean.setCover(cover); - if(c != null && !c.isClosed()) { + if (c != null && !c.isClosed()) { c.close(); } - c = null; bucketBeenList.add(bucketBean); } while (cursor.moveToNext()); } - if(cursor != null && !cursor.isClosed()){ + if (cursor != null && !cursor.isClosed()) { cursor.close(); } - cursor = null; return bucketBeenList; } } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/ModelUtils.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/ModelUtils.java new file mode 100644 index 00000000..7e3130d6 --- /dev/null +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/ModelUtils.java @@ -0,0 +1,32 @@ +package cn.finalteam.rxgalleryfinal.utils; + + +import android.util.Log; + +import cn.finalteam.rxgalleryfinal.BuildConfig; + +/** + * 模式 + * Created by KARL-dujinyang on 2017-03-17 02-24-08. + */ +public class ModelUtils { + private static final String TAG = "Test"; + + public static void logDebug() { + Log.w(TAG, "BuildConfig.DEBUG:--" + BuildConfig.DEBUG + "--"); + if (BuildConfig.DEBUG) + Logger.w("is debug mode"); + else + Logger.w("not debug mode"); + } + + /** + * 多层依赖时DEBUGCONFIG会出错,所以提供了内部接口更改 + * + * @param f 是否打开 + */ + public static void setDebugModel(boolean f) { + // Logger.DEBUG = f; + } + +} diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/PermissionCheckUtils.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/PermissionCheckUtils.java index 355910b9..6f436fe9 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/PermissionCheckUtils.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/PermissionCheckUtils.java @@ -11,25 +11,28 @@ /** * Desction:权限检查工具 - * Author:pengjianbo + * Author:pengjianbo Dujinyang + * Author:KARL-dujinyang * Date:16/6/1 下午7:40 */ public class PermissionCheckUtils { - - + /** + * 数组 + */ public static boolean checkPermission(Activity activity, String permission, String permissionDesc, int requestCode) { int currentAPIVersion = Build.VERSION.SDK_INT; - if (currentAPIVersion >= android.os.Build.VERSION_CODES.M) { + if (currentAPIVersion >= Build.VERSION_CODES.M) { if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) { + Logger.i("ContextCompat.checkSelfPermission(activity, permission):" + ContextCompat.checkSelfPermission(activity, permission)); + Logger.i("PackageManager.PERMISSION_GRANTED:" + PackageManager.PERMISSION_GRANTED); + Logger.i("permission:" + permission); if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) { AlertDialog.Builder alertBuilder = new AlertDialog.Builder(activity); alertBuilder.setCancelable(false); alertBuilder.setTitle("授权对话框"); alertBuilder.setMessage(permissionDesc); - alertBuilder.setPositiveButton(android.R.string.yes, (dialog, which) -> { - ActivityCompat.requestPermissions(activity, new String[]{permission}, requestCode); - }); + alertBuilder.setPositiveButton(android.R.string.yes, (dialog, which) -> ActivityCompat.requestPermissions(activity, new String[]{permission}, requestCode)); AlertDialog alert = alertBuilder.create(); alert.show(); } else { @@ -47,10 +50,6 @@ public static boolean checkPermission(Activity activity, String permission, Stri /** * 检查是否对sd卡读取授权 - * @param activity - * @param permissionDesc - * @param requestCode - * @return */ @TargetApi(16) public static boolean checkReadExternalPermission(Activity activity, String permissionDesc, int requestCode) { @@ -58,4 +57,20 @@ public static boolean checkReadExternalPermission(Activity activity, String perm } + /** + * 检查是否对sd卡读取授权 + */ + @TargetApi(16) + public static boolean checkWriteExternalPermission(Activity activity, String permissionDesc, int requestCode) { + return checkPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE, permissionDesc, requestCode); + } + + /** + * 检查是否对相机读取授权 + */ + @TargetApi(16) + public static boolean checkCameraPermission(Activity activity, String permissionDesc, int requestCode) { + return checkPermission(activity, Manifest.permission.CAMERA, permissionDesc, requestCode); + } + } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/SimpleDateUtils.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/SimpleDateUtils.java new file mode 100644 index 00000000..65492b68 --- /dev/null +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/SimpleDateUtils.java @@ -0,0 +1,17 @@ +package cn.finalteam.rxgalleryfinal.utils; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +/** + * 时间工具类 + * Created by KARL-dujinyang on 2017-04-13. + */ +public class SimpleDateUtils { + + public static String getNowTime() { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA); + return dateFormat.format(new Date()); + } +} diff --git a/library/src/main/res/anim/gallery_ucrop_loader_circle_path.xml b/library/src/main/res/anim/gallery_ucrop_loader_circle_path.xml deleted file mode 100755 index 0364d754..00000000 --- a/library/src/main/res/anim/gallery_ucrop_loader_circle_path.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/library/src/main/res/anim/gallery_ucrop_loader_circle_scale.xml b/library/src/main/res/anim/gallery_ucrop_loader_circle_scale.xml deleted file mode 100755 index 60e7eef0..00000000 --- a/library/src/main/res/anim/gallery_ucrop_loader_circle_scale.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_angle.png b/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_angle.png deleted file mode 100755 index 218d560940177dee5d3a935a0a31a67bae528ea5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1080 zcmV-81jqY{P)Px&@<~KNR9Fekm`i9~RTPF((_(8=O@-R}s3w$3DTo70pzS1rnTX=R7Y+&mXPu@m zojB;EDo!M!G+>7gw1XDGLMb$*1L>fkI8g@)O~7asZ3fzheSP1}UYDKgN$$D#o@jsg z?^Lfzu^CdRor<9j>1WJ3*If@kJ!fH8_+)g z3D$6zgYXYnl+;qTS^9hcd!g70U#w{r{_G*v42(o>qhEj{a1cHVd*DOx8Mq7XhhM{+ zF#4IS_Fv#(SP7h_V=!)V4gEv-7%U5G)r97taqcAfC9-2YN`wg*37$aT4BN#!bo>WK zyzko$6#X2*2^dfQel)Zx-=yD-6fcsz&UJU2@oL>-ik+IbI|)SJmC)Kf1%HE)q;d;v z3oeof)aeKoC9n{eWRX<BbQK8ZcY zIxh0|T=xJ7tVgl!Pk26zxg6s{hYPuJ3Eh(;Zl?YmG)o6BR$tizR=bPOaY+c%4hON0N-uJ6+&A zo@}orIe;`#NAzKM7S`bE_9Y-tCdujK{5;Z!%vWMeUBnCN>Td>5B&R#dsqXJhazst! zwnp9Q3w#s`(g(hnUAL>|@oOgO%R zzh7YfBsDqhuO$6ylHVj*iHMq-PSIXyA?iMSSHphz6tq-6gW}}8sQ(t#qz@;4m>11| zM{#i)%WmdH5j|;)A!Aj$y@U;Q0m9yRLM?F0FNV0VQ!B?}^nVa#Z|ZN1&!Yk9Ohq#K z1ag0UO2HS5_!9IxrVR3ti$wASBSwCNPGOYcZ(B<^h_{`~zN&3V{`NT!o!Z4POhY6V zQd`Sd?w4K{mZc%p+r}Px#*;3`=R@0xHFm7>L##1&W!F`I(&mZn%r83CtNwFf6A5{A z{ta6>Fq%GxBN|h0ox1AXo_w_{3*QBfz&RMT{&CsPt@yc^X0n^O;d?TTz(MHN(*r&F z`r&SP0G@$2U?k_O*z0iF;P&J`8XJDxxQv{o-+ORb-jImPx$SV=@dR7ef&mOT$aF%*VrkNqU53oWhQ`mRTBZTi@`FG2N%yKJhT&||U~bGNW^{xJl=ngUUe){rOz2*L2py>J zXyC1a@HY2h1vM50yiou`doU_0cnyG@BcWXqpNa-v0bqlY9R<8l&@=iSk`f9Io&zA6 z6537xV!Z07*qo IM6N<$g5Px$Ye_^wR5%fxlRYm4Q51&9vVw?+_;DJIMy1iH6e^91g2EOQGzyJGp-?Ck5{2kB zeuan-0X0MaHdC$G~Jp8J68grv1(oq#mZ0Q?lueJ`DBTsHviju+9r z17*97ARUmL^vL0(aK3;ZM0DTLe9Z~80yRKx2|YScwypEvoJs$fN4Wg<00000NkvXXu0mjf1Kh*9 diff --git a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_done.png b/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_done.png deleted file mode 100755 index 70472dd9e2aa4f5ff0ecb276053c316e8939b25b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 220 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbB7JIrlhE&{2PLN<-oFLNEG?6`` z!6MDTGR;`vKl`J$gHI$RzDfA>y=?E|=Q{2qS9&I(@Js^(pF*5ngcIA78E>}~^)L&p zZ;x_Xm;7tx%Nf@LoXdqDYRs}?W6`?6bNso+ENeEltPK`j?ej9(q%#~g=U4}MT)b=e zLq^pgpzok)?R$3Th3)TFFzSEVV43A0+dOaCFZSl-gagSyCjgxjXt0ElA%i#l*!klN R-T_`DP~HFl diff --git a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_next.png b/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_next.png deleted file mode 100755 index d1b1cddb7306f944b98ff31789ecf436d448ac34..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 461 zcmV;;0W$uHP)Px$he@}kO-ygcWzESn@8t7ms7tvXP!C#|G9Hto?EFHBhT}0IDkW#G|K#Km~Vqdi(=gG zVo+dQg$JEPzK0Qm)Zc>f6g+~)Ek(`mWKdu{1J62%d;>!UslNr|1$Y6CD~f)D-V|YbT8-f-$i}K64{syQEuz9u zc5-&i#&8avbiz+PpXL@(VJe$xxO2Px&j!8s8R9Fekmpf|}K^TT}Aw?vG2pSAZ5JANYq5%uB*usDy7FJg2{09nwh+vb# zUJL(2e#8N53qcSBBN&W##T$y6=<~$=4wKF9IlIRdeBnJiJM&#$X12#n^ z`zYhDpuUPqVGeUSX6{X}xZ==rn-(!i#}laY2Y3qhLn=m5&QuZRGN!pV75HpEu*S3M zoY}|N)7rtZ41qosR~P1t{AwARNjfI%Xn+&g#_lv|Q!%D8X9$`Zu_wWB z(yr6|fss=k@Lch%YJxPU!UkS4mnD|T;{FH?_!#bib+Kj1oTa8kor;NNIzyb#P*IQI z6s&^`BYo7+U9l$HzDx|UHjwfA1)AU?^n~vRzb>`!ZhIX(lV;ln!tX2%Ysq*I z;7-^Jr3Yi3tD}yXNPLdQH>jxluzc&O@D@Za)oDEb`)5T`}Q%k%mWuzUQMef0`qf*4$e#PR|O|d8sfu&AXzUsiw$q zxB-oy!W`x@XK}1+HZ^)41VUA3Wa)J%w}ItnU-sy>#_AnpjaY1Jn#LtCJ&KCzpOW6at!gY6brbg}yk zxCT94{nE>zJ8vSV?F>4mjkfwoV;HLyxGg;^;_!?lb)Nd@Te-Cv8yHUYEc8!-mtlM* zq{8fTOdD+*El>J!gl}Vv;$fXk<({iNJPx%yh%hsR7efgmfMR>aTLdA+;U5~6^1C~$>e3qtx!|r$%9)-JWx_f9;SKFOdgac zl*=E16vmA3qDfJj2ZV$)F>d7=4U_xlJ6XGRmOcBNv(Guos?YhY-}SOd#p7R-dP@E-c17kZ!z2B9JuMf6U13cpI^1Aa$fI^>dOq8>u21*6|bVt1EY zc@F{KhbgLQybo9465Iy;%UIa@XBe9ZUY7Ze>Bmqk$hV!?*TV#JbnQs=6`1!F~m5l_x1}o;42jl-oWuBx#9vB_wZ7VFfyT}%O+YPC99sx4bd*a4c+M05~n zx~;fQl*VMVa%BoB-h%RLpXdUu?;&a9*9xoE?LsG3H6&gvF8ZW;0&O0?_+jsmQ(s4% zKjVMW|Lan*38OD8{Q%@WleZJAsr5OJ(@&K{SiPfk?d7vmz0-}8FzbQ!?|iPzGhWL} zFW(19*BN^dvOcPx#!%0LzR7ef&Rof1LAPBYAhufEzv}D9Uag*_2ZZ70@Px$j7da6R5%fpl)W!RK@>-Kh4{*rD2R|KDOaM9*hHhyD3r3DL`_6gdYy#IpP*7v z2?dEr#8=QL=oCaEu?n2Sdz-i8y$!$Qn3;Ru+_`h_*nBQsdCWy9K@Ysa6 zGllIMc3~JQ&;~QG1BWmH^H5ifcsJk?W}yi}8F&R=;4XBAYlB@vZ|F#@EyX6h!w0lN zs=TI|)eDx~Xr^OONE+k0r`~|q45hCdEJsouEF@JH{u#oW8RQdAqj88)ZNpQ9b5(`~ z_-^tdlPw742dk0MUR)fx1?NzJN?03g zRhjh}?7-$>sk0uubAuW;GF6{N-OS-ZKzS>Wy~Xp!I$nTJSG}jTwYL z$?IEFH~DmY-0N@v+KylZQk7K)?L{bo58sa7!#?Px#>q$gGR45gtkWCH&K@f$<&&C1l9KjjHC0sy)tw=<|LI?>9E+FpU01_(~-~twI z;rDx!=}FBDBY4R-UG=KErn_@qR1eYuY@>D}>)_O~3H!6rqh$f-c&q+Ai<>4N5UWQ6 zd|mlERJfbm`EFHR1AJxpPJ>uWANH_Q5=cEwD4IM7ql+fnVX7`cr#XV^q4Ht$I+$a( zp#>!^mb!giclpi20x!m23k`+)^USS#q&6S0WU~u-doyk>Po-q& ho_$iajPW0CGsKqu`mkL((I4nw22WQ%mvv4FO#sURS)~8~ diff --git a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_done.png b/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_done.png deleted file mode 100755 index 9e48718a60627c6da372c9963f4fbf4ad1f131ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 151 zcmeAS@N?(olHy`uVBq!ia0vp^LLkh+1|-AI^@RheI8PVHkcwN$2@AsV*LUD3uA*Tl0JLZqoCWk$YSlCh;ewa;4 yOp$ELyOFQre1gp&-*1^pS%O20R2vU714H==$(sw@)VhH-F?hQAxvXk44ofy`glX(f`tn+kn4ABtn zy|j_5DL~{{VJnw%hf_-xQ+4Y+#ez(aBh%(BU)r8gT2P>|Xz9w8$2qmv|Ci?Fl`qo& zv#07@xx>1uc@f8EF#Ab#ZqpO=`*29qd9G0CAf>+dDnKi+;+)3*8O@Wg0?TEyeNm8TutF3A1l rO`hI3XMyc2?mPdun%qSu$ZuuMYwDWE;j{b&(B%xCu6{1-oD!MPx$fk{L`R5%f>lsifTQ4~NEQFH@h6a2K=*u+wZRyKYcK`d<49Rye465N2;DPk#z z3$PZnvPmO0;t#CiIm3J7n@_;P3y1rEGjrcfnvHsC5^h5WTA`$ezJ)vJhghzLa_iUF z#C(8jSb*<6JM6ld>{0s;i#7!*4BJ;ruirf>-%f1Y$9RMB5GY)~ zv2-EF@Z+9@`huFrb0jWrVIgDHzx+fz%vJC(pW-X03yPbGF>}^fYfmQG)kP<0Kl2zS x;0EH3d9%y#3`gKC=2CZ%N#kwkz@PruegKY#PSq%yrg8uP002ovPDHLkV1kkB$DRNH diff --git a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_rotate.png b/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_rotate.png deleted file mode 100755 index d812eada9cb4ae213c7b9c4e767b4e944624e3fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 380 zcmV-?0fYXDP)Px$Hc3Q5R45gdl1nQ_Q51$ZxeSy`iUAXev4P|-7)VjRUtnh7ANUFWfecJc%$O(?*~`peqnX<;53%bA}KM_vVe z@&aKj21l&FH9Eyw^rhw};;^Jyp~pj|Hv`+zzIB45p`nfPsS1(Kf*55rDV>!NKOBwp7eGTb1^obrD>A-j-eqL zdfD881%FYGP&q{(@d8+XfMKYT=Qson@(TNK6=QQ}FaVkIZQkQLczrhbGi-tRdMK=> aJm(h(B~D)ZycH|}0000Px#x=BPqR45gtk&6w3FbqUP)j_gJJxVue*rcPtCfOu?hhiymQ33U&!=KzaA5u!G z?a=6rFp4kTy(?DY(sPA6hNb5#ae)y=L$57Qfv>$^ zC4qQ|Xx7xzkXXl#M}5<)(2+@=UJwm#r;|BSizAF8YT5@Px%OG!jQR7efAmb+_IK@^9L3cf`P6*ed#LaYQ|V3A;D;lE(2t!)&7pxyQndrLtg zC}<(6EW}1ZLWp)MqJ>(hpdzt|&+prv6DGQI?_D21`0mV}bMD+bbI#1&p;h%7BIF?K zgBGlYx9~9Wo%XM_lMyb$EBI019rkJ14QhX{8SFYm_$OF`YcL68uo*VOD4c|w;EOE6 z9k>OJwVucsaDW@I7wUABfSCQ$y5QXJgTBGp+*r{!f6hFX`78Z(74ge1m(H7-J}7S7 zK<5~ohgoomD`hd5BbV;K%c`>&N;z`5obg@gfZHKg_%30zfI{2pSXj&QMicDXmlQd1 zQ2Xz*z=dQxmF)W0!WQVj1RRI14s$iY^6sZ$jQZn^9mL=6sp#i#udfY9Ui~77?+qi+0dv!>E?VX91@M?^gTIHNs3x1*LBzb}vhu=b z+s>W+`v2m%G9|83QEQTCk#-4AgZt?o3@T?ekWBs{pO}2`_*&<-%Ko2xJohl7U+l-Q zwQ}@=a|*l1j7#eQJqcsr--1mr3fiuMr-(~`1}bxgzo=b!tkU@8=M@)y_un*BmOB2f rn!JfIhrpS&z^Z!#kHG!axG;VKog9f_q@BU>00000NkvXXu0mjf2{=M~ diff --git a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_crop.png b/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_crop.png deleted file mode 100755 index 36e4f362a7a3b598159b274cae7ea0a19c0ce9a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 325 zcmV-L0lNN)P)Px#|4BqaR5%gMle-E6F%U)9H$D-u^K)$cR3BJqEm#Pmg&^4YAC@Y5uVj`n*+4dH z;lOp0%*@H`teYgRy>LXe+>rOAiO33?RJ|$T0baa@#=ep~9kv14Laf<9?9{PPU>B7; zi1~!3Bf4XwB|v?awSF2Hq3rZyCHxXl#Cj;cX+Q%TE$Og>^O~g*_E$)9f|`+JUZQP? z%>`n7X?!$r0KnNm7Vz~Vz&?sk1~7-`e^+LoyF(8AXkaq~gNp-lW_yTTOd6iVHa!=C@H5N0NaEt9_8|vFy*%<4hqL*q{Xg&x XLTy*-2Ix#i00000NkvXXu0mjftQ3jQ diff --git a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_cross.png b/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_cross.png deleted file mode 100755 index a2da5b9605c244be8dc3f7b6b82839bbea48b68e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 301 zcmV+|0n+}7P)Px#=Sf6CR45gNkU-;6uG znK68IdiTz~$2{Y`qU<@^-k-43fIx}|GZkb9tvr`mEKvs%t1t&;1AbcOSwd1D?oiZV z3CbFx0aMiwUhi|pGn4BKR-ouq|68)FvDgH?QCUF#n@qBkWgoU+k(|69%LNmh^GW@1 z`WyA#>9eJN8Qkj~=#?o{vIb8Wq$TwoID#^Pazf@oMzRHFT{wX5sC@n8CfUi}0Im|=LL`sUuP5g^00000NkvXXu0mjfYpHuI diff --git a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_done.png b/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_done.png deleted file mode 100755 index ddf1cd963b74c89c9db8c84e7a7e4fbd624d07aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 161 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`Gj8J;eVAr-fh6C_v{H@GZt@;+?a z@WWcb{PLj!@f8pMH|}T*(_7y8(4=%HuP$#n!=vv{r0nFS)|qfl6IgNVzQY^m)duSi zCUS-3P@Yk6QDy5Dg-EB(SC}@psI@7xi=X9@XFUwGXxS4T7x_nxvw%znPgg&e IbxsLQ0Cns*xc~qF diff --git a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_next.png b/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_next.png deleted file mode 100755 index 8f972bb0b0e6ffc11b7fd6db031b1d2d613176a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 303 zcmV+~0nq-5P)Px#=}AOER5%fxlg$bNQ5c42upsgqHU5eVa1+YXecDns%7R#k!h%F8dl z&3NmXbNbHvo;l5Y$MXz@VK{*mR1KTGM0g3(0V=lJu}ZK8Cy;hfbXe^&!2m8GZ6I$a z9IFHya06)#IfvCQ6KumBqy=Q{gkzOp2Oc2JAtS5LWW+ddfRvk z2I`GZlkJ(uyNCpm@ZIjESSOH~4HBTcG6nPRy#PpTPx$=1D|BR7efAmAy*?K@i0gKfuCTA*~Q=^}nzc3$GVDo6{m`ZNwr9Vk6jCD2U`w z(OPRwEu<4g-|yH7dw08ciEL8McA)IOwyDwBF zjs{x9pxxSYgD!&zSS|r)Vx2e=XyK1`R&fSgqAFa711c0ZuvFDlujsI{+0@yD0k-~E#5|Ok0?_Z`gCZI^XLA;98CPZxblnSc3 u43l$e6M+^VE(|N^IQvNLtN0|6IEr7Cp^zLaCOl*S0000Px$v`IukR5%fxlS?Z_Q546ISGfui%7hX51Tr8a8JGwoiIM?IDMLPii87)*GEz)D zN=l}rD3lnuSES_aDg)*9`yXd(ySeuq=U>15SZnRI_c?oQ$N5_sn44i1P9P3XunY6h z3h59?jYJ*6rw>v59q>y!iLDVP(@^3W@9CFd88#sXMUW2#&;k*VPr16`N5hQFscsne zK;nibxQT&&g^6Ebtgm_jR}Hiupa40_z)!gZY=cRv{#lFka}Pm=TPO!Vl@c%o?_ei< z&_W&G7<*;#Q5yaUFl+2y2XZDor^+HrhJdOg?f~qBS6aL885cGAr*vrp@CZtL3C^`Q z8Pz1DRAw`9mPunuL$@4ODl^q!m2TMmZu%glLRd6*f|6c9F$9(FU=OtR4)nfVwb7bWZZR(WHm7W}@veed*Pj?YW;vsb z^@5VA9>)%tWJ>H-i=L5@4C7$$bj*AWVxZVcsDWxQnrF}nZ^n?=cVSQ|ncb81dJsbp ws4{X0?1OcPgOaN7&tU@wAp)VL4TP`00JrRbxCH?eL;wH)07*qoM6N<$f->FJ6aWAK diff --git a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_scale.png b/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_scale.png deleted file mode 100755 index ac363b773e6af9c3f35fb84fad39537e0b1b6120..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 197 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VV{wqX6T`Z5GB1IgdQTU}5DUS# zlOJ*&P~d3Ee)BiJa`qv|gL6+#`Wt1C)%CpGbMMwN+xbzkDk*0bx#HS;8SaYshTSPW z#p!=Z?ud%3^W@F`9F2yhZUr}13UA({C1Y}E@#`tk|5y)u`>W=jlKB5_OKkgIkqHX~ v{{>h7oFe&f+Sekd#hvfGE}oiIbV%Bck=x)LPx)Qb|NXRA>e5nMnKP?dyrw-@;eWo@ z`qp0S`_}i^`%Fxnr?{XYzb4VM8r~0Yfh*vZa1lHOkHRDHF#HU@4?lsw!2cW;V9_Qx z4UfY=Yw{%W@4^l6LOAbmmN&zLu&y(6$*b!rcrgrYC39;O+D`A~0efJ{z;CFZf;znh z8jgnIW$;FLJA4T4fM3EtU{%jo)ZGJL?YC_tZ54*fHdr;}JL;Z;D`8z+Plp$v>n`if z4nI>@X&w2+2=A^u{3ps?xDbwuOHl9x`~hYM&A$#?K?kk-VSeB)%Gbaqu>@tG!u%Zb z?x2msnaWNXB3;~ z6wXu|PGw_nqVNcO4H_kR192yA1Z&X}qh;D{L~A`I-dfhd7vX*Nx|XF~Klz+;qiA|f zm7m;lt%qyOmRow$yI;%Zm(_dsI|#$EZdq)oT5lW6pbOvI$FMLu>=Ufhcg|hv&^a5prPA&oMBnw5Hj6W~A_3LPog=#|R>V)Q{+Cle6|ymMUSR@t9rIqduiyE$P%=V#`4D}UB$?028_E~; z(?g_xBOG&T19csWQ^l~46u>(nJRL6YFHjFnwkB<-fspYF+;80{pe@*$HQ@*k6OK6I-VyZE%|0r@p3H_cq z0S6-L4c!vlctU1xNnlXjxL2w{y0h^bm~ST4Hp^A`0W}=UgHn|%mK~MjNkQF9a8W6h zoupIacET$1&Aw!KwrkcUx2mjEo~ANJ#;?1hz;`6yt2A&1hCWjbEX|06wo9Ge`81+T7lXQeGQ)gumywqm-Qa+!JgLKVmTR_dYp9b>iJ425Cump~V>;M9*BlsR?=~7^ z*1Z0>v78t1s z%~sgh8HTPi!lNLcbJ-w2v`#?}`899_bVi+#b;kJ?;c}6O6?G0000Px%6G=otR9Fe^mdQ#3K@>&fh;E#~g}VqMh#&}p3qeG1A?U(|3pf6jzvIqX&@T`X z98hsU#R2tPvBOKnq$}y9%0(_*x?Wks>Gxt+<#OrzWXPBCVEU9yBZis1iSyV?Apu7q zI>k!J3C`nGg#sLfdhE zzzywrd~Es(P5Txx+RCKLT~;xm?4BxjS*gSt9822Umb!$aou1y3-r|lsLcK_$AsY8d z;PG5%%m%h=cueyj;{F%+_)pEPG4=!7lG?V`&a7GiSJ~NxJEHGj0ImS??!X)p>#7zV za2bd<2SjiKxXtMgUgAXnk`H;3se@lQ9&rH|0MMzFfaxi?ew-*;26aq5V+*%WY~chM z1#p&)pRk47Bkself&sGDOr(_B1sMfXqJ)qBTP-kpCU!>c~rhda^72~(1uRtQTE53ZiKPIch nd^Q2IX1|%iW(KonAnW{Zu6{}==lPf700000NkvXXu0mjf#Z?y8 diff --git a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_cross.png b/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_cross.png deleted file mode 100755 index 443430be6ca9441a87f425e7ddf919bfd3978e4a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 555 zcmV+`0@VG9P)Px$1lZSYSb#8dhrrp=DQ&Fc<C ziWAIa2F$%g0)Il|W;A@60c-wdJljWZJW?17Co#dG?-)}Tgq{PJ$o>J120AsMqCbZ$*s>nj1; tC=JsW!?YJ&SaVrhU^JM4_QANc&>vgK7ef1)vvU9d002ovPDHLkV1gGf_lN)h diff --git a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_done.png b/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_done.png deleted file mode 100755 index e588817f2268cce4e625021218738872de44f7e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 236 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpUt&7LlfAr-gYPTR zEUrIwPr7dvviuot^XbI@nKcgcHYVmws4w1TqhlWW(^7Yv`Lq{h3I5ZbCSSZIbT|E8 zx|qJM;hDy{QeHgex35f*__j(%a{0sf8;j>os9dsd>V&GqV$~;g{ChV2x#(A+er(B) jr^Sy|wE2OyuC-wdZQJV1zIxsokRv=@{an^LB{Ts5RUBS> diff --git a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_next.png b/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_next.png deleted file mode 100755 index 6cd8e2942b27b49dffdabe4f8bfa707870d8c3c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 555 zcmV+`0@VG9P)Px$ikbyYC>tduYABSXM9oUcMz(hR zN482$6G}=V-yh?5Wa@Ui*W%pkol{TmJdG?Q?C0Xc+5QOJdjU|Mv9xq<5rQ&vo4y6XsY4cDcR3md_7-x1~tuG3UbAO;`~K#Tc8 z#B+jHyF>31E}JCDxx6Mp&bW3+Q-dnwDPc-=9GYqnplaF1VeO~k6Da`uUlb~pI>x15 zg2?xmp=spOEa!hHxvQRl221;hzQET~vH18cZ*U06E#9uf_--CWoJWED1KYLd8HrEh zJO*SZv8x#0&7+9(6nL`}&~JK1;?tPP>L^RJS+X###CP*3Vm1%#l~MXd&q#b4vt?kf zigIt7jqm1B#B3edCBKpM9=I^uwiD3H<3!$*J3fusjw8eqTzbzmn6(1?hbbHTaQwIY thoU2hEXT6fq+b}zqk}BOr=T}9!8gSWIeF7u+t&a9002ovPDHLkV1kMG{TToN diff --git a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_reset.png b/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_reset.png deleted file mode 100755 index 15f8a7b2dfaa10150985fa89a0d04114e313e4f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1295 zcmV+q1@QWbP)Px($w@>(RA>d&n!RfkK@`RP2odoE5k$0*fDkaG5d8!4z<^>3u@FIQY;0_-(x|Xt zWkM{p5J3eoC~0cs;4t%M=H7c| zcjnH#mn>Pb$g#90{ax}iAnq3X#9nc|xJCqD#E;^%I3?Z}ABo?^1w*$Y9}vgIPvWmg zVuLL{@HKDXtsN3)#8}Z;IZ&;qje2Q1NKOm-m6KE=gL5;GRQznJ1=4KGFy%y4V zE?9%)aWi65h1UFbweJ_Z#HzsmkhoV&$Ktc!*l0_SQPV$g8k%_0S}5CWQ9E}S#@!QF zh-HD8%c8|(5^12pr&u%w!F^;#G-pY0)ZY`-ugyCeSLQC07Ej#J1dx%4rVEY1cx)OQ z#OauKNS$kHqb4qz#%*)qh#iIaC77MLyZ=CdGov&1n!C4J9Tgt0qXcAS# zn;x`TthSWu53VsA9Z{ZljtOu{M6jU_@%TcUO<=^FQ{HtQnQ6)!r0NK~=zI|5LUT-A z;&JEGJepgWR?TMCXtl;w5PC&4Ka}T0pXX`I%QouHMMJ&jAI&X%P|Z4eTdnaG*8Vl; z%Y0f{MLcTIX1>te!Z+2dV|A;wT!mD6!}&A6RmGzQZRQWnnc0HAvfz~FDxAg}H4wZC zSf)YLwS+<&)}9#UiD2~NjhRcRu1y@;u#?i~Cox=H@2rsx=c{cK*O5j;;&~(7R`0vO zOy;;)28U#152G!ORyoK*%O<^HS1RyB7aS4C#8_k=WM!`sMZ}xPRjND|?Fq8kk6LHJ zGV>}?<}w!}-t>_MpNM`EN363$+3)OTUFNXmifWEe(U5~O;>{gDkvtVG)(_PWTW3y* zCbL27EEN4hQ$@T5U8f4)Z%xp5)el-{pybVU{6f>MK{KK`O;itouYER#GQD9#Hla5D ze(*vxU!PTHpM;R8(Z-<>twH!SmGz~5NS5ZTtauB)L6w(He@uWUokrm=^%$}|{HvX4 zw$W!`3~vEauL?vT5&Hs;@Q((2U})>jZacoTj( z;g}Sgh@rHn<|yDJ5%K9C6fuci3)mBWV_P6jM~?XZ5>c?h)}OHEmsrHC9i&)tu?6xa zH^niL!>}RtiacFNy&=-a7=NquKJZP9IRys^Lj1MEizrja7d|^4QW{emxQ~#l$3_3U zYS9T`gDpNX?>6eoMO`!QQj`I4kGM@_$^7^K>>-T{kKbbuEk9UMI9UJy002ovPDHLk FV1j=5W~~4K diff --git a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_rotate.png b/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_rotate.png deleted file mode 100755 index d10f0c9967614aa0c74a5b7b72792f18d642ab10..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1011 zcmVPx&tw}^dR9Fekm|KWVQ5eV1xEsTWh`~G{9wsTbF!G?hh!Eu#qEPZ652DmOhzOx3 zCB=hsNt8>?gUjT83z6KLK^V6Y8qB!={$^IKvu5pc=A5&)GhhAATI*Zi`o8b%z1H4q z?VMQp(vzVRVJsAY+9DS|H1LG-DqMl{@B<>1JiM=jYw#QXq`+Hjx5FR^UE1Jr8N7j1 zlJeQ=kL`oL5Q-Gzr2>4xGSSuHb48{ZF2sQxH8qi1Y(J%7FTcm23;3j$Pbpms*anFb zQ{rW?1T?R@f)Op0{-8y)3zAKZyV!ICBb}&hfY(OhmRnE+CHIBCwUF-)O3>CHo&pab z$nPEcdcac9f|6Y|G?Mvff}9+rPmhvxr4<9U*uH`O=|EzKi$uvXscILpi$ zBN(pR=f-i{uk0`_Y4~n|lAB>0hEyMgpP%3+Ww)Q(u@(gwud$6nsCU3e3Dkg{jIUm4 z;WEn8;=c-ll9T?1 zCT=mfa@18s(B6yBfv^>H+kK)t89NN_zZm1Qj!;*G?{ZHbmlRV!Zi0Q)kp-DaO#5-C zU3jb#+yvXHBTJG;+>P)Z%5(Tp#=XFZl5GoG+1V7$&uL2FI=EM`k2;!zXccRzyP{KC zvyh+!wL@+eq6BYwGMVhrWlhza$nG4}MnT)6|0zQW)+#9AO*-5pmj@X~px3TRj}`5p z*F!&ulM-5Pg74Ag$5};a~(d9n%`UHW7WoqnB(E5P`*%V+5APbkjN`lcS<$H5+G*L9GYT5p=t zuio#wLG#-7XX@|JYlF}v>4;U(Eiex6VY3c~gLXweQBt$v1SC2veWZUFq$IkPrC<_D zRMuhl6fVOl(Cf1b5{)r^_puuQY0F|p)`D>uW_bv|`qY-O6yjkIXrY9Wpsw0@2wjTs zcmQf3okY(vZVu>6Lz5(Eawi+CGs`%b1Y@B9^Z~#Xz5Fl1MJR)ZkdmaEpf8A$?g_b2 h-9Wa_HKY--`~|zM6`W#-XkGvS002ovPDHLkV1h|w=?VY< diff --git a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_scale.png b/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_scale.png deleted file mode 100755 index cdb822575c7a16594bd961e028205abf453fa78a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 267 zcmV+m0rdWfP)Px##Ysd#R9Fe^mca_ZAPhrw?Eimxv&WVqrh%=840f0_7+>RbjxnC~R-OrpO7mRc zB%hbdAdB2`6tjV5i}euo&W~Cg@u1)B3El@Qa+x@&M@zPuZ%Px-eMv+?RCodHTw91%RTNgMDI(JZ^`XeWQ41ow8Pa4)>GWb|K_FSg{PbW^_#kBz z;WQHU6o^GcJp>j=Pk{xJUA&ZHX+jTW*ie6xnVHpyX-$;%edAffa?L*bob&(tT%4H& z-|XAkYpuP`zMu2Ym@%W&vIoYtETMS;=c4LNU^*}n7$4yuguehsRQNOEe*l%FBAqw` z9+)3t4#H``I3NxE2c|E9Z4o|3co-NF)Q(nm1HAwp5fXbLZxt{V7?yN9TD2Jn>9jam z{m}C!z~1enxxT_Gl`VuZyMVX`=bir54+38RJ{xq|g3v~^ zBJXNc-tRGf3(9V8MM1{8^T59Y&<=COAI&H?H+CA_7h~{2X6+B#3t_oJ*(;znAO>#(a(E3zx&spfiMIq(*601*41 zMZ7SoL6hqw!bRjvq-ikvKH%OWjo$!e^7JI+Hm1x~xXAXmtc$lX;y4MpkuGx|*m9$a z7T~(hD(fUtblZdI<0>b;Pr@xhBo9*|uG^KT9Bt(_d>+Jm!`py4k#N3@+6(Y__Is3< zH8>v?ZUT4#A{%R7#q9)k1N}f+;{4CsqJM$Z_1eLF5|AFqa4Qg+cub>{v>qF0d6xS> zIxo$&*f#L-O{0(KymtX@6YaUkS4qmcO+^Y>B!z*(l@1-+SQ}@LN+R}XTQ4ci4SF2u z2TXe#fXGX9WUpdoB@P4EkVke?bOUOMF*>BteDd0OU4FSo8|~A)I=&udgwE4(p2#dM zK?Zqfi!OgP%4biGrI{$v3K(A#%bmS|23h$`b7*VoM8d_Vd30PFr|UeT8KO8337Us- z7oQAcYZr&O)MwmD%aAKf67ro$D5^t{$d!=un2Xr+ghxU;*OKeO)Gd=r_aH9vBvi!% zQJGg=j`EcaROT5|1T#Div<;Mm`O|(v<-~g#mna?U)g}( z@9$5WhCM08)WN6g+3k*XqO*q>U6YN>hAC%~4ivpTh?7UsL*{Yu^b9ar+GjILNVCD3 zI#hxVyGErMP2t!G`8Z0d z8&@w&K99itNfo3g=IunzF_z}q43nmlKQVcgOo|hWFiz$e(M1ROE&{d+W7R`(qHE~7 zdS@%`dE8N%Zw>8cmudFgc|adfc`DM0d{C<$9yx$KZdDopoyYV9|f*Eq)ga z;zX@+V@^iWVOmd?cums_M}hl_E~?c^>;*jpYOE1bCL^k&58el-^*om*}2m9mnCX%cWBwJC=Cj&~-R6 zf>E9q5X~6LQ-f~oHir;9HORi#!8({_kD!ggk|rbi$?Y;Scus9Ic||5)Hp-qhX;+d{ zMH2Dz5>4xLqSg2^2+&WS@sO9YS?senEwsfBWy-4q+Gb7(NyHwl>)e@CAxnAQuLsiF z!V#bw$@t2c%67<;*Egg&_gmS%4S$SUe|E1?68c4zPdgVB+e@UuzIt|XX?U1fCNdcY zT~tJGw^2exi=;4M$fv&q;85xTtRr+olX{A)=TaUQ5Fxvmi2PZ?5Hf6sFy35<5{B#@ zp{WLeT8Ar6NBD-OwkfU$yW~oqz0ub4T8?jq1W_cRy-{veNnFnmee9)KDT^cd+96je z;)5pbMD{p3z;3jgX=EoVH2`@SHe^}o4iRf7_l(wnrLo-AE8sN12UUx}MJw&p0M;% z51a`<2CDpnngk2?1GYyVMqWqdt*?-QRsMlwoSWL>3d+o%2jx}$sjl_QSY#{*uCxVJ zNb@ox&XL^yRAC=^DeU+N;PlfA@VcyW#2(oP*g2AEZph0#+0>!`D4=b7A8CF|Q#s-s z=~`^W_$??e>Ws>v%MrpaDn!2xSD~zu#8un1{m~8B3LZ8vk8>-(G^+z&0a~YxuS0ni zrWu&wCiVhu$XzEJ-I!4ST!{1AJ-{o#kAT);ce3pP3NsVN)VZjl$^&7XY(?G-vm>!S^uW{GJf`l_uW)>;i1BC@TFPbko_xf_SmZ z8}gGt-VXd5I^F=d*bPhKJDYBR`?b){{2DT!11D zpa%Ya3hV?n0p9?Xpdy`U8_ZXsGXX9d6M^v&Xw&fsyyT$s2>up&l!mJZ{s)8Y9~ost Rza9Vp002ovPDHLkV1jE!BPjp? diff --git a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_crop.png b/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_crop.png deleted file mode 100755 index 7decf1a39ea45a3a82598c102ab8f194d4c7365c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 827 zcmV-B1H}A^P)Px%^+`lQRA>e5nmcdQKoH08a)d+*v{3R0$D^X+Gaw;RP(-3gaRmjDLP3!fsgRN; zO&SU)C@3gskf1=K;KKk3578n;3gp56FWpL(*;(&+editFkw*6IjCbd^GrKGvQipA4co`&8Y%FiC=~^On+9vP_B+^o2d2>zImfV0J zfaDnJ_LAa}v2sl(Nlw5IK@x)HnogEnfLB3M%x3YN<-MFtI_@9`;Ku=2W_&b`wUI;H zz-yo=X0v!sSgvVN`mp>Gt$xE9e{*ji?Hq8@B8|^+SD??U0w~UqlhzN|Ue z>m(hEX<)*>gvP>>*(@->%DxD|euM2Av@B+UpMgZmtOQGVlfX{{uwP-jN-{yr0q+1r z$}C}r0;p>?1-u=A-HU)Fv>D*73fL>8i4YUOPXHp7@h)t!u$+(Vfj25(7fGRztbx}7 zB4zdqY+6{(OSZtFUjztynbFsfEP*!xB4ze7Y;|EdKdk~wF91TYml$<|v&1A0q{C63yvrF?Y5^Zc+XN9U!{bi%hE-j2Z@n(LpDGS?FRjP6>k7n_6 z2W&BGnwYx`Yi7%$ZPx%czd7dnzA=qI z-SM2Gm5m++-gD7Z604Cs`1koKc|~kiJX0Zs$pV$y6SO=QEM6w0!1zF={unK*8x{{Q zq<{$M3AymZBWg?Qf@OCmBt26te=bfUUp%0=q-t1p20=<++nW!kkT330T-+WgdBLvy zkm||sX&))IJ7}Ty7tQP_4ymRrIfHz0i{g;>=grKPhZIv5HPKn*iyIW@_Y6{vf#^f$ zeWcW`q5r?+I&5U=MO|+k&fJiC@XnSM0|GndZb`YGhEra2+cqYp_`~^#jEw~#75G@j>gviRAQkp#bu`AN zKuG!X@0n5=`G{dr{x}e_b$8Rd3cWzSI9#48u>rS`8>izD#LQ~+(nI>2+M$G1@sBLa z4XJL-u0gMm6~8DP)c(SmC50i?lpSl)Yh=Yw3J0`5cV@UWq?)p89eRVT5ZHa%ADkJg z3{p+mxgJd;E51|Mqy3qg=E@<}l-(Q9TV%y7gLD6maRLV)g0+im(Y?L< zb@d>-f-g6{LQh(3!N#ab}Qj)qGauZ2Mqx2FOBd1%E)XQ-tDMLPx&0!c(cRA>d&na_)jVHC&boiQd%Oe03fMU>enW#L~?lno6V8x~edQmkm24I4GG z84Kmd0+}LV7Je;83FSvom>NnbF-jul`W$(tF}>&9&2w_zQ{SF@&w1xLpYMC`o!;kp znwlJW*-rSCL=wxR2ak(55ki^7*A)9irG zKsOS(G7gZhjG zkjRy>&z~ey2MlzgM~ab@KA5SU|1=QKLr)XAG9K_J$Khfs0c7IlU6n9eWL7in6{fFGR(Nh+6XT?-e6oda< zM{*CUV*CJl!(=lBi4hXZCMPTO`a7(f_=K(rvzYnB*dcE!8e?!T#n5M2gAY~IgkXO| zJz_-O$S1RaQGQ74BvGOG3hPFU+)T_9Yi~>~AsOYr**;jdCdiWU3%T_e87`^CNpVvT zAuB#oTpNd2Apuf0*sb_LakcX2G136aZ@1raK}{ZWx?>P46aY3O**mjhl;R3yiWq4C zThJ-X1+`bG7K2!!08kF3&Lb;iS-nV^B1RfO*@wPlxuEt0b;Tf7C;*iG=SCaqvbQ!@ znIc9SK-s3fg{-(sG4`_}fOAlz{pQ_} z;5PP2G=Q?n_Y7Hafnw|vXaH;IC9>i)#n=b60LmViJc3wpf@16gS^(t{<)P(*+A%b- zmWuJ~E};N&O#>s9Ivumj^p^OKo8nW^zGnO5QX6C#l4FWNG=}6~^A_XsY^C3A;^gpZ S_c=QN0000Px+=}AOERCodHn@fltMHGe;9}^5}f*=MFa+8ciP!x;?1JOl5gczcrF2;p-A%tus z#FYpR2qFl95YUAiXCbJl8v_a|W)ca416c@y1QVH22{9@Nz7ij!{}=BWYtF6iu6w(> zX9niLPgU3Bod2AzuCA)Scg2cjDUHC&(%NP#S4sVi!X{y@a8(aVR{Y${%G!)jL~K%ZJPvIMwy;^m2d;2#MHu2N;9_LX zsC=vy7I7okhC_@SoZ;T6Fr%w$~bIg~a7n2<+jIEHF{FbW3CT@J} z4CBx{>f|HN>$B=@b+y`X2*%^trf~QM$^`DQB>=t-BdRx7TZ)1M=c)j~1)t16OYyx@Vkd#A8_&JcZpOm&6O~_C zX*sRkAy1<`lJ-+3=a12EesHOVo)gl>jOujgWQo&@e8`} z#<_l9;G5W>k~=uqN2foTBnD9#RjGIAV6S_}_^Yl5xyyYDdj+hhUlu~$ zmVaC21fWQo4i0wl5nqiHDY592uT&B?Vy?&~1nCta)NlFMReov2P#eK9vmZEa#A2Q> zY5px3Y0~HCwWxo=KIl~;v|)M5sW)jeIM~Ej<3dU-=DkR6aSdqH6>+w6 z+bedQ;z`|i z7?Xtx5Wf5&JS2R`MS-*t986aRsDNMN#f%C*!4wJ0{w7CGk=?m+8$pE;oNJjs!({!M zz@t_qPpe|Qs4`=D;S{q_0ZIvu`TwjkPuWF7X<>lO9HDB~9=k-4o;R2^8 zg{GwPHQ&}kF=Y|R8TJXmZd8~)(NKiC5qt9%ifwE)Qi5at^EKqN2x)?~*BWI^E4Lch zVuKdmt(=?HL4sp`U#raLjuZT5g~x@QQn^{hnBOCD1Td0;#W2A!v)3u}g%I92@@ys_ z6LJVX;%jIldfc(cHKGHDNp+-7aLn%Y%CH^^9U#y8XiTUp_~>;Li#{1uiEqep zIA;3>W&9LiL3-F44Vfk%xuW0SDGs!8bWq6|9J9S%nQ6h_M7AvRcHX*96?i5e+M{$_ z@C0^IF@Q7?95cUBnQsKo@q)_kw?+e`_~vyHgF=D8tPplOR@l0~qRHTxH9jk!5kijS z&kOeng9yHbdhneXl*$p+hMmZ7FYWPvN_?~CtA659_|y;2$a-e6O~F(+{LsyfaiWqg@%`ceiO}kO#**S$=|t(vHBS=SR{3l`U0)yY~klJHtA(KcWx=-C-3jU_Utf z;BbwPwdAmRd&R6dw$;+wZfCf{+53TSwS}{p8Nn+*r?RCGBsjv=^T#KA%OcBvW=RO+ zJ!-T3cc_X$vAHV>60gsyby9`;EY)y`y~=sS;EoTC3I|Ml?DNkw*DS!sgoP4p#}G851D)tT zDugzD9*)`GR?;<)tW;|jTCo*(NR(5%g91Z*L>N}+iw<=8lfcj(c{srhjzdeW&VkjA z@`r@oL0M52;>QI(4xa3RvmJgPV80PyPX*Qqn|old#iPW&t4bI(`-JJLhHcmHl))*% z-_5qJu?>esFC08^IyWmc9UN?63!6($INu!?{MV8kK|?3HE6Px)!bwCyRA>e5nro<4MHI)ozB0X)B^ABIN2I+aDPMh%9v^~R6s3LfLnTB66;csh zstY|RA}E3&2ud!!APXUTU=)N&MfNbs(9Fyv%QQ<<>!#N4e>xMpede|A*=O&44lelJ zIcH|gnzi3rjINB2VVr{FT6g-CgFk#ZM<4K~q{zYU^Q zaxJ)mH1*5SIjW&|F%`?zPgLYAO>x+_co+T3j$b+YqJqg-Hl6=Nw`Ncz#t z=l6{7JprSy8pRUIQH=Qj#N-8`i=o}6Cdz+(%IDVg$}CP{@Ye%=`eIOU^gHXLfK3?Mapu9r@Rg~om$e!0w17>F@9;rKPIrLT zB1vtAhyMH7`u9(3ZTnRIg{zOk6nFuYm)G9Xxt4Mz@0}!LwP=~?wgq;At+I{lwkzPR zo&Y*6;M$8Q--hkmvOL$Rx=otlbsqQhl1lqp$A|)MIM_->r_`;ZM8~Z=!L?HV?;NO8 zBKIAV9U#c#+a%B{@$-xrUvEIkHN&cZFvdv9I%66CcaXmyzyi=gpjGtBL|K(9Xgz^c zeT%x!;=gi?r(rrYhz{yp0jpjet15aEvIAWH>k)TS+W8AS9b`y(XjyL^(!Qp@zet5E zSk*61cQD_V2ReR1yYs#AodZueSgZKHM--CjQb)OJs-8`nk{lfgxx{}?Dz zv~aG4P_Qe}Q5G33{b+`as(l6MA)^RUCbbhne(gmkD&tBzJ(@4NN+IKF*E99aFdSMT zy3ImckMUF6=b#^Wj-|7nmyNMdxgOnXAg@(i>0%!!(+iDl+OJ2qDVad;jbIGMlxxtx zAErT88A^u>K{J~573rO!!D44Zd9+UV&k7l|v~Q+vDd?a<=iFQBrSe>@wwlFbU@FXp z>EJs$rny1%GrkR;XlQAoVhnwkLCg#nsiVY0zlfH|5Ulosu4s`#xyD+BAG+mQE;AV6 zb8tD*>U!M{x?e{?VWP!FTTv*N%{%z#7*lIXX`=mlA!u>RJ2+!+54QW^e5i~l>F5D% zCvwm@+f1o^`4-S>o{Pk8OIZgyj1Dtl4$Okda3c7|(-G5ZP^$WVz0?+#tN0wqbs&t5 u0{wfV_SkM12HO+p3GJX9yaG*LfqwuD#bzA#(i5Io(C<7wAfVQYH>Pq zS|7*eIp;5lKGazrX{B_g$j&>wW%Hc0mmLPDf9k{vo-3NQ^m5;aT_116_RTbB(=p<7t u!>t{H?+>i-<$J$YHj!6mmmy5?55@>5?gp0~^Mipw#^CAd=d#Wzp$PyGCzQVc diff --git a/library/src/main/res/drawable-xxxhdpi/gallery_ic_corner_selector.xml b/library/src/main/res/drawable-xxxhdpi/gallery_ic_corner_selector.xml index ffe37819..a6497e2e 100644 --- a/library/src/main/res/drawable-xxxhdpi/gallery_ic_corner_selector.xml +++ b/library/src/main/res/drawable-xxxhdpi/gallery_ic_corner_selector.xml @@ -1,7 +1,7 @@ - - - + + + \ No newline at end of file diff --git a/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_angle.png b/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_angle.png deleted file mode 100755 index 68eb67e05e2ed971f34b1674bf478da04090b09b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3179 zcmV-x43zVUP)Px>B}qgH!q_svg zHJCEAoMFpUOh~q*wPZp(6k8j zVtHhza9Z#jI4J%Z*|bYoF67Y-5@2Q+Sz4r)F$KLS3@RW+>-~>x{JyYIh>0nDhk&k6 z#hLwhpH*`uY#O!+UliE&m8GXu;IMGS;Ll34-UZ;ibA|JS3j`bu=p=6y-X^?CC`xR^ zHVEs5ZwgG8>^|8PeNTA504;mzF*^TVt)@IG;LxIAd;UXVtFThQdA$-kn2NUucM0qm zi`s+Sap7IU-BG!p>3t-Ko_Lc`)G16s`-IH`XRNx3(fBdp0ileIu`C;=p{JHwa7c(7 zmwNxVW&SWVY^LXd0+|bfmS2*q-(LT7&E^WXg2~8n#C=^9pGjywE#j!m~nFkZj%$25)k43%2DnjP>B!;_3!2 zxlR_8-SR&)aH|U%uu*chr^V?L%D=3jt|o}F78O~8<94#s<@Te|#BMOFahy+ByoZIj zV#-^C<3QQ>K^{wTecX~n*4F(I)7WzuxuMiMs|hXk)NjI3b_ zmUS}MR~HM{2)l&G1h1Vj|1*+pBxPMUv1Sd^G+4yJua(gI1P=Lh)YC#7EZ%nrjUz5{ zQ^vw$H#kfijBcHKt_ofud`aLEIV=qalx`I96UkA*3)nDi-K%u$OetF-e4t9DRp|PP zlz73~Q$+=19o2bYkyLqyNv@lQ$ErLB6+|&cWj^b-f5r%_);h}y149|KLC4Qr#kt9sV&5I!J7~+ z6sjc7U7LjcLR=^BeEQ9Af!)>{js@?Oj&;Hkp({cW*GwrR`39q(L?glhHDyoCYfHY& zCvB;=aPIVi6xSEtv5`(yln8Vv8$U}2ZjGai8*R4v{USzG+?b;8^xAHS(NeUIlw6T| zZ;k3`>pkw2mzObqGEx`}+gChk14R*x@W!x~8!$$aM?oJp<8)L@AdvH9gxmT; zI$q1HeOWezfaSLP997IYD^zHoD|3vlBAcnl))~@ew#(j>?oDghof_3er_#{wc;|=h z@swr*mNmlKDoc5unM6p1Ha+m5UqBfZ_qk}fg@TYoU^#yWVn z)1tMlZ3~;U9qnvvrjS**bV}|^jKg|RdEJ!y9^@M(E5*(oi85>|JW9|ThnuzNz+taa%?S8DMO-6!jueW7vM@|$= zvZ%xAAl-^2*~(iPreo@2%BGXpJiSgO7R*522s;u4YJR>Yq5oilm&ZDp5SW+X!8+gJ zcfxHoE=1+4|G&jYBXM0l15$adK<|OJ*O;-uATowVdZ4Cup9TL%#o?aKR z8F{^MEK$L3@!0%5m&p4+%QnJ`>R-IV74v^uk-k5b&~qjs`+#^=1&qL?=m|03AP}7M zIv^Gw5>5#&*?^^bI0fBkyIQ-;V22b_YMP8?;`d&ieL<|S;QPY~xm5|CWf7d`J1As# zlLB_swxpB3Mo(*FLSzbS;S^4P7*)*>nbulo40?p!<5>D0hwrfudl@zJQ!_;6RoZ}6 zuDql|riWvRGVG{|+R0(l+Yu&I40TRAc|`}g)`nA0|3$DD?6H`i~vO%>(^EoIYHVlGW& z{3yZmSVgXwQe`=U)J`^FN1WQ0IsCfWx2Xbd0l2QoBV>?e4NTq4AIwu=@;R)}Fz>x2 z_x4gaRo1RykE8^|OZ8Ysv~o7L09@C6M7UVEM7U6Zo)Yd8ek<4w#k=($lh+xaj0HRI z1gy}_gHt}RpALySo?NtIWDFcrRgbH~ZmW|SBep-w@gXpAnQq$KPSoA9##Nmj^d|yU zv}co)#Lnk@=8+e$vS&}Pqu3eDv!N&cUX_j;%=^}!wDza4=lr~HLhetrc~eP~sUzjL zZboWm)ppZ?;4dBN)egT&>~ANG`MY==6SC;niOjMclyx?y17Z-wS}EKb#Jz>Z-}}9+ zR)Y#E=Tm~%X5Ldf##kkrm{i#^m$|9(8{&%Uc%Ln$+<2r6*jz`2J?dnQ*zef;ObOko z_M*245tvl@G664Ak1I3j7_iSR(f~sugi{G+>HKy$jj9p(_xLw#JlwGG( zq%fT=$q6AZNaSNryvB)D4`odui&Z5T!mMdA-6_WUm^q^FY%ty^yvDST1Nmb@nWKX# zUSE=*ExcYfT>@60cWcnRNIJ*=Iam#jty87>4Sb&cT-qd()cWTF_ z>h!?X838+`yvypWe5|`W58R|;-Y7evyye}g9ha)h1Ki{v61<>sowcB@%Ex-U^FT|* zID2?Ok5nw-!iS}SAD2wu<_Y2)d!NfDDR8wEZs^Mb~jHcA_jS!&PFQ{GP>>>h`G z%g?nO?Hu^UZdJYIIw|r-S>W%H%)F{9?4us;5APL1J3igVx@)a!o3v+5k2LtWFidxk zpOn4-6hg3gvTm;tMuIk~6NL)@JTkM}pWrW^MUH&kbZwdUO9_;j`+lmAMI zuag6CG=Izo7@>SX#54<52$u@o94k(%+zrCl1*Y$5ML2J_@S@=Lm5buwut7bakPTlI76@a?@xV;wb9*o;cz-oh zM<6)>Gwr=s7^;iix;Gv2M`4;RNj3u66tLKN z>?)TCO9j>yo-Ki$AZMun+Q7j#;IB%zJ9u2r2Ze_O)~GR!Juvpb*aI0J_#e)w$K4G! R&HVrX002ovPDHLkV1i4+A>{x7 diff --git a/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_crop.png b/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_crop.png deleted file mode 100755 index 8dfce883656c9aa47048f6618ea290823fa775ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1175 zcmV;I1Zew-P)Px(QAtEWRCodH+uN&6K^zD0gM;IiTarWyB}$Z%`~Chz`5XKhVPMP;6*`98SrEcUU0+|0Y?GulmSm69_~e> zl72urQ?+NRYD#wZcp}H-2X~3Myxv_9}c1k%x)yy>RwKi(|P_dMAF^fz6_6{vsa`5CtE+tA<=qS4K-ZLpE9w>^o> zi+n;GG5#k+-3DPR>xLVA>z4^J0oMVJPdYXzsXlAK)qs2Nfk)J?0OT{HbcI5DH1kiMOZf!>j-TVKL%4LPAsJ#M_M+nz9F62n{~PC?qNW zf;Ru-5i)DQ1ps)8kkC{)@pd8VQnrA6J|93RBq=A}&N{iOEK9(-nEVrjgr>@gx1)lR zvg`ooK;kh%AxSyE0NpOB4JpqGa5g6X2qB@V@}_un%m#24Ci}1<9>4o*nz8_#35^E` zwZf#F-}!BADp$2j9&kD)dLJR7sdD0NsZct}k_Ma#iF*izB;~GngiaQ43MO~AA>L-R zb4^JC@;&SwgtX#R`A4+b?HBoc0YpO!0^U8 zW+I?1jkh&0)pt7iy0N&4gt!oOV|RU7`Gu^?)R`B%a7cTOSh1D!v7ggWv|3n>kv!t{S!q<*@*{1w&|ZU+U>%}w_z zfSSVXpa8nL>0Sj;Q@9-zKsPtts{m>Ww}S%c=B9fUKuzIxPypTBbgu%aDclYUpqrcS pRRA@G+d%Px&%t=H+RA>d&np=oXVHC&5TnyvVeqQKpn=B{x;bjlSRj&Ap!h)V*wrYJ~ud%;P4$twq~=q|Fv zFN#*@4av@AaB7qRBhh_iiJug$)ZVN!yJ~||gA5vt9wJM8r)atMW|i5I4xAcfU>j;j zmiR`|QteGUGdo>4HOSyG=rOWH7e$M;H?7RfY~a)&3&x@+$P!;DTByCXW@cpzrv_Ox z4n0Gb_)O7!?M<4Qkq?|2WZ?wVfh_TnqMmz?4)Dm*iz1&2B9=>C;$3C77&HmJh*%PJ zN*2#98(?@rPcd-n4FglqD`bgx6wTD$xJ+%aaB2`E)6g4a38|Z|y_GUGVZf=Y&gg0JdA%b zLdyMgJnA2C4&(w%%O@F22xR{EIW?O!V|o$#Y9Tb%q<0ff3e~p{<4ce{UDO)k!6__c z%aA-LCXI069LN>W{YXFUj=SaHq`n`?km(CZuwF|5kJBn3EyyvjjK{sdJvrU<8ympK?zWo3Rp@`UsGv~!W! z&H0f;Z1RLF-3sX0j;wK>!lsDT*`H#u&tJ>3`y9Qytc28^MUB}LIU87*7*5A9V-K>% zX$l*(H`C0bn&H$Sv-VjDsXK|X`e4#yi3O>_IgkfDAdgc!KzmcoS-`15W*_o^JeoRW zmT&?ohS3pZjl=rp)STIv`mbe_DfS5DF)JZ;2czbAonuHYaB7Nu_2>k$#(wSf&TPmP zP7SiR0iCiEQny!o&6%b`;M5@d8_^kLjosQCo0(WBoEpSO6FO%lq;9A7R?HLy0jCD> zGZ0-s*4U=K|79iw1*Zn_)r>A#38~wnz5g;NgM?Fq_#2F_AZu*WUb)Ez4W~x&*@CVa z3FXU!8%n(#$fJxU${u-iah@5ILy`5%g95ouuAn6fhtoF_v-0J^TNcyQbXx#}fpZ{R zF@MJb83z~~oC7%mzt<8 M07*qoM6N<$f<<20TL1t6 diff --git a/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_done.png b/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_done.png deleted file mode 100755 index fe6352d8bcd5b854246aa7d5f2b998d7e8ed1ab1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 479 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7Ro>U|i+LN?KW0afV;{L# zjz18PVLT{k!Lx{S5fCtSI)sEM2#CsXH9Abo-K63>SxxrFyX|*>{++zs{PW)L`znn$ zPv!&~2nQR^Gjkfnm~YHVx_w00@|Sr1<*xtI!JEFQ|NGteBYN%x@pvJoZN)k_0t0Gd zFBpca-{^ZK-|<81zfbYLQ_p|8`A)TW_!wFj@JI4w(Y*Z`>MA8BS+@%GQ_jUt(y2a? zWUY99{$w5Xe?Cv8O;?N5uly9NAM*02+u1(%vy-$_rSl5T$)9bjzJDb8_OI!WetzB< z@-J5S{@X=n3spjX&nUWm^6&XX*Kbo>vgCum<)%w}Ij#KBy|JUd zxar4pKc}zd)|Z=()|bp_xpaKWMY&CK%$^#e^F3-0-{B7xIt6>fm~1 zX1}KW;!R~sJ~hvE_>-W1qX0|`b;xf~o+tl?Px&<4Ht8RCod9n_EZ}Q5eTvD~d8ptWe6phU_NDmPN`XE?T5+rniB3S4`QBtPe%yRpE!OCIT)^8r#alZ4xpFK14 zKQrh5pEGA>&wP`Y7eXYH$x?6`yaDgPRZtc}Q^G$a!b`w=kRH9Ps1Cn{Ic@=>FQq%- zEQ={sIc`$8hePm7$AC=5kF1P`)yn)34m>o%F^kyVhA9h1;Qg1)VHnb(P*M!19aH8j zxY4E{QU=u?pozDTDx$4e(RxHy0U1CwA-Cqairq$=g2-ynr*Q<148-NpR;*|}B5S}G zpos*e*^1ppn}W!t;2Y4y3rI7gtys}|MAm}u8b{zf1Eq@HMw^1jRbT*U;whvV(N?Tz zJtEhEpBhKtJOa}cyNxylksH7u(8NPX@?>i}5V;Bb(l`R=0hnUj5!4}aEBFmGaSzgD zA55u3=#a({IJZH852ox4U`hwvi9VRJ8==~ef5{VkFr`uJ2)tWhybq=v3}DI)xZ`{< zBp*F8X51=>Vo&fE&y0X$#?K zh&&g-l(X5I_;&1M3Dl-ub zuWQDX1L^w2(I()V8REl!I>QMmxFLqDbys*+K7=VpUCnaId}f7QHa^D=E}s@LKzc~G z&rYEIK4?vOAch=EEqM6biRM~*M{i1dJ_~IuYy*9%m7e^zqjM$t`(3@mPi>4P@>f~z zHc_0gEuh`!f%dK5O}HB|V}M^zgVgZUy)XG$DCu>rENpib32O@I&JS9LZccfGY-ZTYxs% zPR5oRx4x+|;o&AeLx%X?Tp%7|;wIss4SJ!Y9Qz!ihIVxavtMrOoH-1_Fq2$ZK#O-NFI zC|^3{deU{IZ+4{Px=k4Z#9RCodHom;3~M;XVH<0X|ev0{Y~Y*-Z16TC!TqEd#~HsIUoF)S#$a3|NYmTS+i#Cv@2FD+p+@JvH~l69Q<|Sc8f5*h)qfhVXd$x zfU+xI3UERB1>vM{Y7wWEzAE(2`g8-{Bz0~RwhG&X+l5s^9riCdIVKzx=7cAOe+$>V zO-X_6!mPk7{%=cQEXHJPI9zkKK@mSBJSVgzx;G9S-~y+Kw~dPMpm0&}1nH_APH=WGXf1^;<*fl*UJS^}KUvhSr7_I*m>~GT7e4XL7*#kC1F@|3$PMzc+Rh6*1@`z&8)GomyujGGJc)_edToW+9T#$f;!pfhp_R2(Im;6<5^Jw)Mr?Sq940<%a3S>73K4_jusDd7 zn0sOOi^Z_D^jWpJrx$GVNWc}&sT)De#NMgx)95LZ)EyCS=#=GXgToo_!{S4OPK>*s zBFEl&S0~Ks9h4Y|B^7Jye+e@~2%S^?7GYA1Scu8H2`oow(u%PINIh^l+#J9-y}?`5gRdje+g()2#pwTfxL)#gEKoOS$q?f7*l@b#Akh+#AQceMU7Zf&jhrp)i{ju#Ak;vNe|py;fOi4JF4vfk0a&Nf_DRU976-|*aGdwI_*6y2j1PSa<=ns`6(ayLb?#TwpAkVgiwx?n~-a0QSNWo zXgHE>RIf{dISNxw46E29Y8>{r{4*-=a_j1e55Kcj0#sY?6cr88va&s<9wtXBtgq;=j^-)xN4WuoNO|8A4pt?+K^-m%q41XfZdGS$|6$>>;}5^QUAFm5 z7$!cP_6b#OzdD#sVTzV$nr-}0DRf|Y*6~qi>o**q=KE>Yze8x+a>VDEkoyo0`JxRP zSxjMyrdc+nR^F>N-%rP}J?b2iD(9b4{oBVGU`XFw@o6`zp;0+5uF({2huRLch&f;h z8EZ?mIP$k0|2F3DRsXidwsj_Lh!0;h@|N4}IRVY8k%ff5_ zE2mjo;v1KFWh|C3Mcbrtis$`Gd1ta`^~%)Y9;A;6YpS~)=+Ua4U5F1|wDPv3Xzbcv)x?CT`r_pdP^ws|>mN8{8jm^E zzopbK=dvsDjhpvk#zw?7g0;ZIbhq1M{0eTuW6rq7;TNi}^5fpF#YYu1GyY*ZM`g?i z(A&dqj&-Q9Y)Za+pg)FiV@ZH)wz#3o+7G z#-DZSA=Vf1(F)Db&bWtZbV7g5Y5a4Qw`FhCK&kU}g7}F*yR!93eB*|8q41VR>np~e zzS$>n1P%Bj@)CsfYe&RR1G^zZf&b|EchCD~O~lVf5uQVq12~8E86Ien^FO zhr;wrvBnLTaSp?IOvt00hc6STk27Dit{B>td2Vx zX4s9Qo}1K#eN=-Q*Dyuv0eea%VI#}Gcc5i^1?>NiI=qZuD(zByR6@HLKeQgOGb)KS zE(Th*Td-Qg{Yr>&OOxmo_|PAuGp(xJ}=>2nzbSzoUPn9;sB zP5Qh9^JyR}%G2S9#h+wLT;^Hgm$Xi=&8~ znQyzDcZ&Bj4tI;=i%l!-`2VuQ3$3qM_!n@>3QMVXNLOlB+hxwo4-eMvE8hK=LDPe<@B=ZX3Cu!zV^Eo+aI;d@3R)_e;g(dTOAq+Uo^UdL2 zYusS!O=vVm>!{7CG$d>JCO^v8DZT~u9%a1QM@;;iUOvt=X_Y_9LuRjFqKE0@4KZy( ze53k4WjMMB;|TK?Rre`t+(3$E;dqu${w(DVr_;+S=P;~JYf^mU`F>^23l@AiWjXkm zHLfv5D>N&Q$2A(e#xD+D5@H>9y1lAbv?0E+`k*p@7h*9{_KL7WsMF9YHXhodanfd0 z8|yru?3G{HrufEci!$ECBG!Kj9}()Zc{z${h_*v*yIRCLvyW!4J&tuDzVW?N8HA3- zM%h1vHmD`r zv@$ua_h)-~t>He$m-%l?d}H(pW%z1lWIKC!;eOgqnnTv>V%2$-`+ObR6b)jXlEBbwKQ)7GWOE(5@C^?;JW0^K9p~)H2G_ zazf0htt^_=Y6s*k6h6$KQ{D1^wC^>2(5iOh6fgDLOkTBbs(sY{IV48!sD??2Mng|L zM-8h`$MZrs`@{T6)lKqEAU0wQV-E9ZQwWXP-SY0eyg-K8F^S6&F{NfcnxIW9HltCz zBUf$$&xA>OFcS+gg|j`(qXn9@YWHijkVHAp4uNgjQa55q?RJP8EjlsYXv@NvuaBrr z?i+I_K{$iL8SdqH%GYSnsd4vH%MpZmRj+b()M-GAT)pE3y8*=9*~~8sG^2vlgV{)P zVpxjb-UU z;bDRIfF*6LwTFdELO8qnn1>@=;XHA+Q4t*!E((1UA5L(Cn z&+|6hx%KG=l*M4z6z*oGbzKPTP)Px+_(?=TRCodHoC&B_MHI(1(^qa-DuqZqHMg(`vvA9WB0~}-p^bt>g)pqppu#K& zE6k!rOxlgeFtIEuvPGVXnT1iN=2B>xS-Dh}xun+b|M0%<`_kHic-+S-O zIcLr}-`trqGxyoNS!t<;<}U($K(CXi<=P&!18qSo@Eh2lfp2+U3qAv?F9|g-a;s`@ zAh-ey2ZO+AAQ$=<;cY;{Tn(0hy`Z9~FW$@o+kqS|B#xqgDYzP__m(w{!umQ;$biM^ z-bdT>KsQiUq+fp>h;y!(bw{w}3D6m&n$E+z<)E0s@oDP-w#@`>K&t3;teFEe{`fdl zD&F1Lso^CRq+YiHlqwiW+dYBJ4}lh-WHf=64}zplq(N>K_IE9I1W%#CxdjZIeiXfC zTfx_0JJU}gw}6&!g(AHj*MhHruYCdkKgf;;VbTx17z8}QRqJsRX$`v& z1cJWTcaS~b)KY$!WbZhz3HaJ7evP$~?*JYJO2l1yHdAh*$Ki4*$X2!kxv{1e3d5wg zW(GI}ve}whuOMnEm{}fv-bj5`(tsHjvfiuLwaco#I1D{$=1X9;-O8t-B9_jjR?8o& z!hml!GMX{dL|QGq1OglLas49BLFGBV8v=)sxhYO*3hM60hI|B1I<%P^Ni(VOX-J9g zz({TBs<;(%loj~+=i*%xv7wml1!#`^r#P>=N17+qG!C&AzH4rMZ ztA?HRz~ZNsXF;%IGQt=PZK`UbDMwm~(fz?4K+Cv%P(v(sq0JI?9r{!PDdSiGa@|l+ zlHTkbUZ;Xi~la3d3uF=yEHq>H2XGmSx0?27JY)z1HcrZ<56Ea zt^oEjO2uv-8g-a!OcLcv4HA(V9Ves=Bn>Ss-5&&zYLW2JqgsQ>R)Z^*>4L3 zn&|%s=$u7|RL$yuE6dI->mcSPY8(NjF@H5KihSxASyROo3g8~2|C-X9C?f(2;I@pi zs7LFXIZD1F%N4+_M$axV@>Lz10+TsmxSqFHU1W?7*T8qk7{qQyomIo8SNI56WAu2m zk*{jl6hKj3{lD4&(W!qEIU+EOGS|50Dy#H#W&*L$27=eZL1!IWB)bBZSvD8GN~P8~ z_A8Lj`oL7@zQciuo`NegSgvO&)~Qw{l8!uGJ}cF`3&i?;NrbRV;T(7?jauQ5HjQ2W z24&indJ~KUPSUwYz#Mng%w1_?;Z&pVii^IvandA8;{q41`_QSOJPW&Hwl-D5{zcvI zgD>(J#L|t!il>xkyc$`pR8D8!VZY+;?{6gSc$ns)Ok+aic;L{T#-iyS{_0#P>u1fH z%75@ssxI9Flp|e=(K_pi>v7?_N32ec_fV<^^jC}Rt;$ovcOiEC4#EM7yH|eL$;b9( z9?I3QzF5~7S`O3`BdrUEAgJn8UZh42f zN~~9npL#vgNTV@IhvimZ#J3xq2@;dmgFX$4S3TFe%O|!lyI^xz?gcu>_4Vbd?CRq= zlr(Ni(6Bxe)2!7Rl#-MrYkc+%ocJHim*M(?E899T%D^4Sj?0%J9(we{KMZ`*l&}xa zdbDL??FZL>5N^chUjN_97*k8RF)47jfS-VmePP}u$hH7^Cw*X}Y&_hU@BIekr-QRW zK1sVt&w*U+TaJ#Jd>WRiYXAjGDt!Z&$*+%dWb6zu2xwE+hcv8Q59Wf6AX9&m=N0H_ z2h60|DG4c;Qli~0iExCB*45vEE#P}_0H`+|1xh12hR}!mt{|T@A7!@#*-;eIE4UIQ z`K8k&a|9nI7bRkjMl{gQ0!i|#Gz3w9G(N=PSJ8_ur^THh4MDNmun2p*6g^Tg4Yr|f zHqe-5b)pn}>#=VHNG)lAe-D%*IB{)i4LlVTB)>y%-l;zt7lTrdkGrtp0pPWl2Y+g) zHDrU*1eAeRXI2aIaYQOtS>3jhEB07*qoM6N<$f_2#KZ2$lO diff --git a/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_scale.png b/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_scale.png deleted file mode 100755 index 21fc505b9ecd6f89886dd900503cee25b1485b47..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 443 zcmeAS@N?(olHy`uVBq!ia0vp^0U*r51|<6gKdl8)jKx9jP7LeL$-D%zOFdm2Ln;{G z-U{?PY#`!tQKa;LG}|6V^-G<1o%Ds`UoJWM(W2^tUEkv$|Nh?n`8ncGTJ-zp*&omT z`F)wa!&@eyL8IZLl!O9T!X7rI2QyBdd$#OqvGlz|pMG3f&bFw&fpHPTv228*Kb=1X z=b!U5pHu%;Gviz?_v2425WQ?2OcLuGL8{-+U_P(c_-xJQ$?+EZO8j!U<0BexdNa*= z8Dk;#fOW}D?_?1p22WQ%mvv4FO#qZPxIzE` diff --git a/library/src/main/res/drawable/gallery_bucket_item_selector.xml b/library/src/main/res/drawable/gallery_bucket_item_selector.xml index ec5e626f..4a6ed0c9 100644 --- a/library/src/main/res/drawable/gallery_bucket_item_selector.xml +++ b/library/src/main/res/drawable/gallery_bucket_item_selector.xml @@ -1,6 +1,6 @@ - - + + diff --git a/library/src/main/res/drawable/gallery_button_selector.xml b/library/src/main/res/drawable/gallery_button_selector.xml index 4952d945..fd509a3d 100644 --- a/library/src/main/res/drawable/gallery_button_selector.xml +++ b/library/src/main/res/drawable/gallery_button_selector.xml @@ -3,31 +3,21 @@ - + - - + + - + - + - + diff --git a/library/src/main/res/drawable/gallery_default_image.xml b/library/src/main/res/drawable/gallery_default_image.xml index 24358d21..c0c889e4 100644 --- a/library/src/main/res/drawable/gallery_default_image.xml +++ b/library/src/main/res/drawable/gallery_default_image.xml @@ -1,4 +1,5 @@ - - + + \ No newline at end of file diff --git a/library/src/main/res/drawable/gallery_ucrop_shadow_upside.xml b/library/src/main/res/drawable/gallery_ucrop_shadow_upside.xml deleted file mode 100755 index 0be54272..00000000 --- a/library/src/main/res/drawable/gallery_ucrop_shadow_upside.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - \ No newline at end of file diff --git a/library/src/main/res/drawable/gallery_ucrop_vector_ic_crop.xml b/library/src/main/res/drawable/gallery_ucrop_vector_ic_crop.xml deleted file mode 100755 index 99b93e8d..00000000 --- a/library/src/main/res/drawable/gallery_ucrop_vector_ic_crop.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/library/src/main/res/drawable/gallery_ucrop_vector_loader.xml b/library/src/main/res/drawable/gallery_ucrop_vector_loader.xml deleted file mode 100755 index 89cb7bcb..00000000 --- a/library/src/main/res/drawable/gallery_ucrop_vector_loader.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/library/src/main/res/drawable/gallery_ucrop_vector_loader_animated.xml b/library/src/main/res/drawable/gallery_ucrop_vector_loader_animated.xml deleted file mode 100755 index 319dc43b..00000000 --- a/library/src/main/res/drawable/gallery_ucrop_vector_loader_animated.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/library/src/main/res/layout/gallery_activity_media.xml b/library/src/main/res/layout/gallery_activity_media.xml index 0e6f5cc2..24e8817f 100644 --- a/library/src/main/res/layout/gallery_activity_media.xml +++ b/library/src/main/res/layout/gallery_activity_media.xml @@ -15,21 +15,21 @@ style="@style/TextAppearance.Widget.AppCompat.Toolbar.Title" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_gravity="center"/> + android:layout_gravity="center" /> + android:layout_margin="8dp" + android:text="@string/gallery_over_button_text" /> + android:layout_height="1dp" /> + android:background="@drawable/gallery_bg_bucket" + android:scaleType="centerCrop" /> + android:textColor="#2A2A2A" + android:textSize="16sp" /> + android:visibility="gone" /> \ No newline at end of file diff --git a/library/src/main/res/layout/gallery_fragment_media_grid.xml b/library/src/main/res/layout/gallery_fragment_media_grid.xml index f40f7cf7..cb38aac4 100644 --- a/library/src/main/res/layout/gallery_fragment_media_grid.xml +++ b/library/src/main/res/layout/gallery_fragment_media_grid.xml @@ -9,7 +9,7 @@ android:id="@+id/rv_media" android:layout_width="match_parent" android:layout_height="match_parent" - android:cacheColorHint="#00000000"/> + android:cacheColorHint="#00000000" /> + android:clickable="true" + android:gravity="center_vertical"> + android:gravity="center_vertical" + android:paddingBottom="12dp" + android:paddingLeft="15dp" + android:paddingTop="12dp" + android:text="@string/gallery_all_image" + android:textColor="@color/gallery_text_color_selector" + android:textSize="14sp" /> + android:paddingTop="12dp" + android:text="@string/gallery_preview_title" + android:textColor="@color/gallery_text_color_selector" + android:textSize="14sp" /> + android:layout_toLeftOf="@id/tv_preview" + android:background="#1F1F1F" /> @@ -68,15 +67,16 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@id/rl_bottom_bar" - android:paddingTop="?actionBarSize" android:background="@color/gallery_media_grid_block_color" - android:visibility="gone" - android:clickable="true"> + android:clickable="true" + android:paddingTop="?actionBarSize" + android:visibility="gone"> + + android:background="@color/gallery_bucket_list_item_normal_color" /> + android:orientation="vertical" /> + android:text="选中" /> \ No newline at end of file diff --git a/library/src/main/res/layout/gallery_fragment_media_preview.xml b/library/src/main/res/layout/gallery_fragment_media_preview.xml index 8973f1e0..58717e59 100644 --- a/library/src/main/res/layout/gallery_fragment_media_preview.xml +++ b/library/src/main/res/layout/gallery_fragment_media_preview.xml @@ -8,7 +8,7 @@ android:id="@+id/view_pager" android:layout_width="match_parent" android:layout_height="match_parent" - android:orientation="vertical"/> + android:orientation="vertical" /> + android:checked="true" + android:text="选中" /> \ No newline at end of file diff --git a/library/src/main/res/layout/gallery_loading_view_final_footer_default.xml b/library/src/main/res/layout/gallery_loading_view_final_footer_default.xml index 378d1b15..e08bc5e4 100644 --- a/library/src/main/res/layout/gallery_loading_view_final_footer_default.xml +++ b/library/src/main/res/layout/gallery_loading_view_final_footer_default.xml @@ -1,24 +1,24 @@ + android:layout_height="wrap_content" /> + android:textColor="#E2E2E2" + android:textSize="16sp" /> \ No newline at end of file diff --git a/library/src/main/res/layout/gallery_media_image_preview_item.xml b/library/src/main/res/layout/gallery_media_image_preview_item.xml index e3b9f4e1..f3c093df 100644 --- a/library/src/main/res/layout/gallery_media_image_preview_item.xml +++ b/library/src/main/res/layout/gallery_media_image_preview_item.xml @@ -2,4 +2,4 @@ \ No newline at end of file + android:layout_height="match_parent" /> \ No newline at end of file diff --git a/library/src/main/res/layout/gallery_ucrop_activity_photobox.xml b/library/src/main/res/layout/gallery_ucrop_activity_photobox.xml deleted file mode 100755 index cc03a40e..00000000 --- a/library/src/main/res/layout/gallery_ucrop_activity_photobox.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/library/src/main/res/layout/gallery_ucrop_aspect_ratio.xml b/library/src/main/res/layout/gallery_ucrop_aspect_ratio.xml deleted file mode 100755 index 5ccf9915..00000000 --- a/library/src/main/res/layout/gallery_ucrop_aspect_ratio.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/library/src/main/res/layout/gallery_ucrop_controls.xml b/library/src/main/res/layout/gallery_ucrop_controls.xml deleted file mode 100755 index c39ec964..00000000 --- a/library/src/main/res/layout/gallery_ucrop_controls.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/library/src/main/res/layout/gallery_ucrop_layout_rotate_wheel.xml b/library/src/main/res/layout/gallery_ucrop_layout_rotate_wheel.xml deleted file mode 100755 index 32e4c7ea..00000000 --- a/library/src/main/res/layout/gallery_ucrop_layout_rotate_wheel.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/library/src/main/res/layout/gallery_ucrop_layout_scale_wheel.xml b/library/src/main/res/layout/gallery_ucrop_layout_scale_wheel.xml deleted file mode 100755 index 047203c3..00000000 --- a/library/src/main/res/layout/gallery_ucrop_layout_scale_wheel.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/library/src/main/res/layout/gallery_ucrop_view.xml b/library/src/main/res/layout/gallery_ucrop_view.xml deleted file mode 100755 index 4884fd88..00000000 --- a/library/src/main/res/layout/gallery_ucrop_view.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/library/src/main/res/layout/item_gallery_media_grid.xml b/library/src/main/res/layout/item_gallery_media_grid.xml new file mode 100644 index 00000000..a7748ee4 --- /dev/null +++ b/library/src/main/res/layout/item_gallery_media_grid.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/library/src/main/res/layout/item_gallery_media_grid_fresco.xml b/library/src/main/res/layout/item_gallery_media_grid_fresco.xml new file mode 100644 index 00000000..3f58617b --- /dev/null +++ b/library/src/main/res/layout/item_gallery_media_grid_fresco.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/library/src/main/res/menu/gallery_ucrop_menu_activity.xml b/library/src/main/res/menu/gallery_ucrop_menu_activity.xml deleted file mode 100755 index fd363d55..00000000 --- a/library/src/main/res/menu/gallery_ucrop_menu_activity.xml +++ /dev/null @@ -1,18 +0,0 @@ - -

- - - - - - \ No newline at end of file diff --git a/library/src/main/res/values-en/gallery_strings.xml b/library/src/main/res/values-en/gallery_strings.xml index e7b354f6..399e37da 100644 --- a/library/src/main/res/values-en/gallery_strings.xml +++ b/library/src/main/res/values-en/gallery_strings.xml @@ -10,6 +10,7 @@ photos video App request to read your album + >App request to Camera Absolutely empty The device has no camera Camera not available @@ -19,4 +20,6 @@ Photograph Selected pictures + cut + record video diff --git a/library/src/main/res/values-en/gallery_ucrop_strings.xml b/library/src/main/res/values-en/gallery_ucrop_strings.xml deleted file mode 100644 index f5f9ccfd..00000000 --- a/library/src/main/res/values-en/gallery_ucrop_strings.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - Default - Cut - - Cut - - Both input and output Uri must be specified - Therefore, override color resource (ucrop_color_toolbar_widget) in your app to make it work on pre-L devices - diff --git a/library/src/main/res/values/gallery_attrs.xml b/library/src/main/res/values/gallery_attrs.xml index 439d2edf..75e7f855 100644 --- a/library/src/main/res/values/gallery_attrs.xml +++ b/library/src/main/res/values/gallery_attrs.xml @@ -1,23 +1,23 @@ - + - + - + - + - + - + - + - + - + @@ -56,64 +56,73 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + - + + + + + + - + - + - + - + - + - - + + - + - + - + - + - + \ No newline at end of file diff --git a/library/src/main/res/values/gallery_default_theme.xml b/library/src/main/res/values/gallery_default_theme.xml index c024499f..fa759c10 100644 --- a/library/src/main/res/values/gallery_default_theme.xml +++ b/library/src/main/res/values/gallery_default_theme.xml @@ -1,14 +1,15 @@ - - + #2A2A2F - @dimen/abc_action_bar_default_height_material - @drawable/gallery_ucrop_ic_cross + @dimen/abc_action_bar_default_height_material + + @drawable/gallery_ic_cross #ffffff 12sp #ffffff - @dimen/abc_text_size_title_material_toolbar + @dimen/abc_text_size_title_material_toolbar + 0.3dp 1dp #151515 @@ -21,7 +22,7 @@ #CC5833 #FF6E40 #151515 - + #282829 #F2F2F2 #D8D8D8 #D8D8D8 diff --git a/library/src/main/res/values/gallery_strings.xml b/library/src/main/res/values/gallery_strings.xml index afba0306..d7cfe7b8 100644 --- a/library/src/main/res/values/gallery_strings.xml +++ b/library/src/main/res/values/gallery_strings.xml @@ -10,6 +10,7 @@ 图片 视频 App请求读取你的相册 + App请求拍照权限,否则无法拍照 空空如也 该设备无摄像头 相机不可用 @@ -19,4 +20,6 @@ 拍摄照片 选中 + 裁剪 + 录制视频 diff --git a/library/src/main/res/values/gallery_ucrop_attrs.xml b/library/src/main/res/values/gallery_ucrop_attrs.xml deleted file mode 100755 index bcaa4ab3..00000000 --- a/library/src/main/res/values/gallery_ucrop_attrs.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/library/src/main/res/values/gallery_ucrop_dimens.xml b/library/src/main/res/values/gallery_ucrop_dimens.xml deleted file mode 100755 index b18a0386..00000000 --- a/library/src/main/res/values/gallery_ucrop_dimens.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - 16dp - 8dp - 20dp - 2dp - 10dp - 64dp - 72dp - 3dp - 13sp - 10sp - 50dp - 40dp - 30dp - - - 1dp - 1dp - 30dp - 100dp - 10dp - - diff --git a/library/src/main/res/values/gallery_ucrop_public.xml b/library/src/main/res/values/gallery_ucrop_public.xml deleted file mode 100755 index b4ab285e..00000000 --- a/library/src/main/res/values/gallery_ucrop_public.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/library/src/main/res/values/gallery_ucrop_strings.xml b/library/src/main/res/values/gallery_ucrop_strings.xml deleted file mode 100755 index 909f3e48..00000000 --- a/library/src/main/res/values/gallery_ucrop_strings.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - 原始比例 - 裁剪 - - 裁剪 - - Both input and output Uri must be specified - Therefore, override color resource (ucrop_color_toolbar_widget) in your app to make it work on pre-L devices - diff --git a/library/src/main/res/values/gallery_ucrop_styles.xml b/library/src/main/res/values/gallery_ucrop_styles.xml deleted file mode 100755 index 420aada2..00000000 --- a/library/src/main/res/values/gallery_ucrop_styles.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/library/src/main/res/values/gallery_ucrop_values.xml b/library/src/main/res/values/gallery_ucrop_values.xml deleted file mode 100755 index 0d016b0e..00000000 --- a/library/src/main/res/values/gallery_ucrop_values.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - 1500 - \ No newline at end of file diff --git a/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/MainActivity.java b/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/MainActivity.java index dc732d48..b5089f7c 100644 --- a/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/MainActivity.java +++ b/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/MainActivity.java @@ -1,90 +1,468 @@ package cn.finalteam.rxgalleryfinal.sample; +import android.app.Activity; +import android.content.Intent; +import android.net.Uri; import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; -import android.widget.Button; +import android.view.View; import android.widget.RadioButton; import android.widget.Toast; -import com.facebook.drawee.backends.pipeline.Fresco; -import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator; -import com.nostra13.universalimageloader.core.ImageLoader; -import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; -import com.nostra13.universalimageloader.core.assist.QueueProcessingType; +import com.yalantis.ucrop.model.AspectRatio; + +import java.util.List; import cn.finalteam.rxgalleryfinal.RxGalleryFinal; +import cn.finalteam.rxgalleryfinal.RxGalleryFinalApi; +import cn.finalteam.rxgalleryfinal.bean.MediaBean; import cn.finalteam.rxgalleryfinal.imageloader.ImageLoaderType; -import cn.finalteam.rxgalleryfinal.rxbus.RxBusResultSubscriber; +import cn.finalteam.rxgalleryfinal.rxbus.RxBusResultDisposable; import cn.finalteam.rxgalleryfinal.rxbus.event.ImageMultipleResultEvent; import cn.finalteam.rxgalleryfinal.rxbus.event.ImageRadioResultEvent; +import cn.finalteam.rxgalleryfinal.sample.imageloader.ImageLoaderActivity; +import cn.finalteam.rxgalleryfinal.ui.RxGalleryListener; +import cn.finalteam.rxgalleryfinal.ui.activity.MediaActivity; +import cn.finalteam.rxgalleryfinal.ui.base.IMultiImageCheckedListener; +import cn.finalteam.rxgalleryfinal.ui.base.IRadioImageCheckedListener; +import cn.finalteam.rxgalleryfinal.utils.Logger; +import cn.finalteam.rxgalleryfinal.utils.PermissionCheckUtils; -public class MainActivity extends AppCompatActivity { +/** + * 示例 + * + * @author KARL-dujinyang + *

+ * openGallery 返回 void,如果想使用RxGalleryFinal对象,请在 openGallery() 之前返回 RxGalleryFinal 对象 + *

+ *

+ * RxGalleryFinal radio = RxGalleryFinal + * with(MainActivity.this) + * image() + * radio(); + */ +public class MainActivity extends AppCompatActivity implements View.OnClickListener { - RadioButton mRbRadio,mRbMuti; - Button mBtnOpen; + RadioButton mRbRadioIMG, mRbMutiIMG, mRbOpenC, mRbRadioVD, mRbMutiVD, mRbCropZD, mRbCropZVD; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); - initImageLoader(); - initFresco(); - - mBtnOpen = (Button) findViewById(R.id.btn_open); - mRbRadio = (RadioButton) findViewById(R.id.rb_radio); - mRbMuti = (RadioButton) findViewById(R.id.rb_muti); - - mBtnOpen.setOnClickListener(view -> { - if(mRbRadio.isChecked()) { - RxGalleryFinal - .with(MainActivity.this) - .image() - .radio() - .crop() - //.openCameraOnStart() - .setTitle("标题你设置") - .returnAfterShot() - .imageLoader(ImageLoaderType.GLIDE) - .subscribe(new RxBusResultSubscriber() { + findViewById(R.id.btn_image_loader).setOnClickListener(this); + findViewById(R.id.btn_open_def_radio).setOnClickListener(this); + findViewById(R.id.btn_open_def_multi).setOnClickListener(this); + findViewById(R.id.btn_open_img).setOnClickListener(this); + findViewById(R.id.btn_open_vd).setOnClickListener(this); + findViewById(R.id.btn_open_crop).setOnClickListener(this); + findViewById(R.id.btn_open_set_path).setOnClickListener(this); + mRbRadioIMG = (RadioButton) findViewById(R.id.rb_radio_img); + mRbMutiIMG = (RadioButton) findViewById(R.id.rb_muti_img); + mRbRadioVD = (RadioButton) findViewById(R.id.rb_radio_vd); + mRbMutiVD = (RadioButton) findViewById(R.id.rb_muti_vd); + mRbOpenC = (RadioButton) findViewById(R.id.rb_openC); + mRbCropZD = (RadioButton) findViewById(R.id.rb_radio_crop_z); + mRbCropZVD = (RadioButton) findViewById(R.id.rb_radio_crop_vz); + //多选事件的回调 + RxGalleryListener + .getInstance() + .setMultiImageCheckedListener( + new IMultiImageCheckedListener() { @Override - protected void onEvent(ImageRadioResultEvent imageRadioResultEvent) throws Exception { - Toast.makeText(getBaseContext(), imageRadioResultEvent.getResult().getOriginalPath(), Toast.LENGTH_SHORT).show(); + public void selectedImg(Object t, boolean isChecked) { + Toast.makeText(getBaseContext(), isChecked ? "选中" : "取消选中", Toast.LENGTH_SHORT).show(); } - }) - .openGallery(); - } else { - RxGalleryFinal - .with(MainActivity.this) - .image() - .setTitle("标题你设置") - .multiple() - .maxSize(8) - .imageLoader(ImageLoaderType.GLIDE) - .subscribe(new RxBusResultSubscriber() { + @Override - protected void onEvent(ImageMultipleResultEvent imageMultipleResultEvent) throws Exception { - Toast.makeText(getBaseContext(), "已选择" + imageMultipleResultEvent.getResult().size() +"张图片", Toast.LENGTH_SHORT).show(); + public void selectedImgMax(Object t, boolean isChecked, int maxSize) { + Toast.makeText(getBaseContext(), "你最多只能选择" + maxSize + "张图片", Toast.LENGTH_SHORT).show(); + } + }); + //裁剪图片的回调 + RxGalleryListener + .getInstance() + .setRadioImageCheckedListener( + new IRadioImageCheckedListener() { + @Override + public void cropAfter(Object t) { + Toast.makeText(getBaseContext(), t.toString(), Toast.LENGTH_SHORT).show(); } - }) - .openGallery(); + + @Override + public boolean isActivityFinish() { + return false; + } + }); + + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.btn_image_loader: + Intent intent = new Intent(v.getContext(), ImageLoaderActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + break; + case R.id.btn_open_def_radio: + openRadio(); + break; + case R.id.btn_open_def_multi: + openMulti(); + break; + case R.id.btn_open_img: + openImageSelect(); + break; + case R.id.btn_open_vd: + openVideoSelect(); + break; + case R.id.btn_open_crop: + openCrop(); + break; + case R.id.btn_open_set_path: + setPath(); + break; + } + + } + + /** + * 设置 照片路径 和 裁剪路径 + */ + private void setPath() { + RxGalleryFinalApi.setImgSaveRxSDCard("dujinyang"); + RxGalleryFinalApi.setImgSaveRxCropSDCard("dujinyang/crop");//裁剪会自动生成路径;也可以手动设置裁剪的路径; + } + + /** + * 直接裁剪 or 拍照并裁剪( 查看 onActivityResult()) + */ + private void openCrop() { + if (mRbCropZD.isChecked()) { + //直接裁剪 + String inputImg = ""; + Toast.makeText(MainActivity.this, "没有图片演示,请选择‘拍照裁剪’功能", Toast.LENGTH_SHORT).show(); + // RxGalleryFinalApi.cropScannerForResult(MainActivity.this, RxGalleryFinalApi.getModelPath(), inputImg);//调用裁剪.RxGalleryFinalApi.getModelPath()为模拟的输出路径 + } else { + // RxGalleryFinalApi.openZKCamera(MainActivity.this); + + SimpleRxGalleryFinal.get().init( + new SimpleRxGalleryFinal.RxGalleryFinalCropListener() { + @NonNull + @Override + public Activity getSimpleActivity() { + return MainActivity.this; + } + + @Override + public void onCropCancel() { + Toast.makeText(getSimpleActivity(), "裁剪被取消", Toast.LENGTH_SHORT).show(); + } + + @Override + public void onCropSuccess(@Nullable Uri uri) { + Toast.makeText(getSimpleActivity(), "裁剪成功:" + uri, Toast.LENGTH_SHORT).show(); + } + + @Override + public void onCropError(@NonNull String errorMessage) { + Toast.makeText(getSimpleActivity(), errorMessage, Toast.LENGTH_SHORT).show(); + } + } + ).openCamera(); + } + } + + /** + * 视频 + * 单选 多选 + */ + private void openVideoSelect() { + if (mRbRadioVD.isChecked()) { + openVideoSelectRadioMethod(); + } else if (mRbMutiVD.isChecked()) { + openVideoSelectMultiMethod(0); + } + } + + /** + * 图片 + * 单选,多选, 直接打开相机 + */ + private void openImageSelect() { + if (mRbRadioIMG.isChecked()) { + openImageSelectRadioMethod(3); + } else if (mRbMutiIMG.isChecked()) { + openImageSelectMultiMethod(1); + } else { + if (PermissionCheckUtils.checkCameraPermission(this, "", MediaActivity.REQUEST_CAMERA_ACCESS_PERMISSION)) { + RxGalleryFinalApi.openZKCamera(MainActivity.this); } - }); + } + } + + private List list = null; + /** + * 自定义多选 + */ + private void openMulti() { +// RxGalleryFinal.with(this).hidePreview(); + RxGalleryFinal rxGalleryFinal = RxGalleryFinal + .with(MainActivity.this) + .image() + .multiple(); + if (list != null && !list.isEmpty()) { + rxGalleryFinal + .selected(list); + } + rxGalleryFinal.maxSize(8) + .imageLoader(ImageLoaderType.FRESCO) + .subscribe(new RxBusResultDisposable() { + + @Override + protected void onEvent(ImageMultipleResultEvent imageMultipleResultEvent) throws Exception { + list = imageMultipleResultEvent.getResult(); + Toast.makeText(getBaseContext(), "已选择" + imageMultipleResultEvent.getResult().size() + "张图片", Toast.LENGTH_SHORT).show(); + } + + @Override + public void onComplete() { + super.onComplete(); + Toast.makeText(getBaseContext(), "OVER", Toast.LENGTH_SHORT).show(); + } + }) + .openGallery(); } - private void initImageLoader() { - ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(this); - config.threadPriority(Thread.NORM_PRIORITY - 2); - config.denyCacheImageMultipleSizesInMemory(); - config.diskCacheFileNameGenerator(new Md5FileNameGenerator()); - config.diskCacheSize(50 * 1024 * 1024); // 50 MiB - config.tasksProcessingOrder(QueueProcessingType.LIFO); - ImageLoader.getInstance().init(config.build()); + /** + * 自定义单选 + */ + private void openRadio() { + RxGalleryFinal + .with(MainActivity.this) + .image() + .radio() + .cropAspectRatioOptions(0, new AspectRatio("3:3", 30, 10)) + .crop() + .imageLoader(ImageLoaderType.FRESCO) + .subscribe(new RxBusResultDisposable() { + @Override + protected void onEvent(ImageRadioResultEvent imageRadioResultEvent) throws Exception { + Toast.makeText(getBaseContext(), "选中了图片路径:" + imageRadioResultEvent.getResult().getOriginalPath(), Toast.LENGTH_SHORT).show(); + } + }) + .openGallery(); } - private void initFresco() { - Fresco.initialize(this); + /** + * 视频多选回调 + */ + private void openVideoSelectMultiMethod(int type) { + switch (type) { + case 0: + + //使用默认的参数 + RxGalleryFinalApi + .getInstance(this) + .setVDMultipleResultEvent( + new RxBusResultDisposable() { + @Override + protected void onEvent(ImageMultipleResultEvent imageMultipleResultEvent) throws Exception { + Logger.i("多选视频的回调"); + } + }).open(); + + break; + case 1: + + //使用自定义的参数 + RxGalleryFinalApi + .getInstance(this) + .setType(RxGalleryFinalApi.SelectRXType.TYPE_VIDEO, RxGalleryFinalApi.SelectRXType.TYPE_SELECT_MULTI) + .setVDMultipleResultEvent( + new RxBusResultDisposable() { + @Override + protected void onEvent(ImageMultipleResultEvent imageMultipleResultEvent) throws Exception { + Logger.i("多选视频的回调"); + } + }).open(); + + break; + case 2: + + //直接打开 + RxGalleryFinalApi + .openMultiSelectVD(this, new RxBusResultDisposable() { + @Override + protected void onEvent(ImageMultipleResultEvent imageMultipleResultEvent) throws Exception { + Logger.i("多选视频的回调"); + } + }); + + break; + } + } + + /** + * 视频单选回调 + */ + private void openVideoSelectRadioMethod() { + RxGalleryFinalApi + .getInstance(MainActivity.this) + .setType(RxGalleryFinalApi.SelectRXType.TYPE_VIDEO, RxGalleryFinalApi.SelectRXType.TYPE_SELECT_RADIO) + .setVDRadioResultEvent(new RxBusResultDisposable() { + @Override + protected void onEvent(ImageRadioResultEvent imageRadioResultEvent) throws Exception { + Toast.makeText(getApplicationContext(), imageRadioResultEvent.getResult().getOriginalPath(), Toast.LENGTH_SHORT).show(); + } + }) + .open(); + } + + /** + * OPEN 图片多选实现方法 + *

+ * 默认使用 第三个 ,如果运行sample,可自行改变Type,运行Demo查看效果 + */ + private void openImageSelectMultiMethod(int type) { + switch (type) { + case 0: + + //使用默认的参数 + RxGalleryFinalApi + .getInstance(MainActivity.this) + .setImageMultipleResultEvent( + new RxBusResultDisposable() { + @Override + protected void onEvent(ImageMultipleResultEvent imageMultipleResultEvent) throws Exception { + Logger.i("多选图片的回调"); + } + }).open(); + + break; + case 1: + + //使用自定义的参数 + RxGalleryFinalApi + .getInstance(MainActivity.this) + .setType(RxGalleryFinalApi.SelectRXType.TYPE_IMAGE, RxGalleryFinalApi.SelectRXType.TYPE_SELECT_MULTI) + .setImageMultipleResultEvent(new RxBusResultDisposable() { + @Override + protected void onEvent(ImageMultipleResultEvent imageMultipleResultEvent) throws Exception { + Logger.i("多选图片的回调"); + } + }).open(); + + break; + case 2: + + //直接打开 + RxGalleryFinalApi.openMultiSelectImage(this, new RxBusResultDisposable() { + @Override + protected void onEvent(ImageMultipleResultEvent imageMultipleResultEvent) throws Exception { + Logger.i("多选图片的回调"); + } + }); + + break; + } + } + /** + * OPEN 图片单选实现方法 + *

+ * 默认使用 第三个 ,如果运行sample,可自行改变Type,运行Demo查看效果 + */ + private void openImageSelectRadioMethod(int type) { + RxGalleryFinalApi instance = RxGalleryFinalApi.getInstance(MainActivity.this); + switch (type) { + case 0: + + //打开单选图片,默认参数 + instance + .setImageRadioResultEvent(new RxBusResultDisposable() { + @Override + protected void onEvent(ImageRadioResultEvent imageRadioResultEvent) throws Exception { + Logger.i("单选图片的回调"); + } + }).open(); + + break; + case 1: + + //设置自定义的参数 + instance + .setType(RxGalleryFinalApi.SelectRXType.TYPE_IMAGE, RxGalleryFinalApi.SelectRXType.TYPE_SELECT_RADIO) + .setImageRadioResultEvent(new RxBusResultDisposable() { + @Override + protected void onEvent(ImageRadioResultEvent imageRadioResultEvent) throws Exception { + Logger.i("单选图片的回调"); + } + }).open(); + + break; + case 2: + + //快速打开单选图片,flag使用true不裁剪 + RxGalleryFinalApi + .openRadioSelectImage(MainActivity.this, new RxBusResultDisposable() { + @Override + protected void onEvent(ImageRadioResultEvent o) throws Exception { + Logger.i("单选图片的回调"); + } + }, true); + + break; + case 3: + + //单选,使用RxGalleryFinal默认设置,并且带有裁剪 + instance + .openGalleryRadioImgDefault( + new RxBusResultDisposable() { + @Override + protected void onEvent(ImageRadioResultEvent imageRadioResultEvent) throws Exception { + Logger.i("只要选择图片就会触发"); + } + }) + .onCropImageResult( + new IRadioImageCheckedListener() { + @Override + public void cropAfter(Object t) { + Logger.i("裁剪完成"); + } + + @Override + public boolean isActivityFinish() { + Logger.i("返回false不关闭,返回true则为关闭"); + return true; + } + }); -} + break; + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + SimpleRxGalleryFinal.get().onActivityResult(requestCode, resultCode, data); +// if (requestCode == RxGalleryFinalApi.TAKE_IMAGE_REQUEST_CODE && resultCode == Activity.RESULT_OK) { +// Logger.i("拍照OK,图片路径:" + RxGalleryFinalApi.fileImagePath.getPath()); +// //刷新相册数据库 +// RxGalleryFinalApi.openZKCameraForResult(MainActivity.this, new MediaScanner.ScanCallback() { +// @Override +// public void onScanCompleted(String[] strings) { +// Logger.i(String.format("拍照成功,图片存储路径:%s", strings[0])); +// Logger.d("演示拍照后进行图片裁剪,根据实际开发需求可去掉上面的判断"); +// RxGalleryFinalApi.cropScannerForResult(MainActivity.this, RxGalleryFinalApi.getModelPath(), strings[0]);//调用裁剪.RxGalleryFinalApi.getModelPath()为默认的输出路径 +// } +// }); +// } else { +// Logger.i("失敗"); +// } + } +} \ No newline at end of file diff --git a/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/SimpleRxGalleryFinal.java b/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/SimpleRxGalleryFinal.java new file mode 100644 index 00000000..05bb4f41 --- /dev/null +++ b/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/SimpleRxGalleryFinal.java @@ -0,0 +1,157 @@ +package cn.finalteam.rxgalleryfinal.sample; + +import android.app.Activity; +import android.content.ContentValues; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Build; +import android.os.Environment; +import android.provider.MediaStore; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import com.yalantis.ucrop.UCrop; + +import java.io.File; +import java.io.FileNotFoundException; + +/** + * by y on 17/07/2017. + *

+ * 使用相机拍照并裁剪 + */ + +public class SimpleRxGalleryFinal { + + private static final String IMAGE_TYPE = "image/jpeg"; + private static final int TYPE_CAMERA = 1111; + + private RxGalleryFinalCropListener listener = null; + + private Uri imagePath; + + + private static final class SimpleRxGalleryFinalHolder { + private static final SimpleRxGalleryFinal SIMPLE_RX_GALLERY_FINAL = new SimpleRxGalleryFinal(); + } + + public static SimpleRxGalleryFinal get() { + return SimpleRxGalleryFinalHolder.SIMPLE_RX_GALLERY_FINAL; + } + + + public SimpleRxGalleryFinal init(RxGalleryFinalCropListener listener) { + this.listener = listener; + return this; + } + + + public void openCamera() { + Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + imagePath = Uri.fromFile(getDiskCacheDir()); + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { + intent.putExtra(MediaStore.EXTRA_OUTPUT, imagePath); + } else { + ContentValues contentValues = new ContentValues(1); + contentValues.put(MediaStore.Images.Media.DATA, imagePath.getPath()); + contentValues.put(MediaStore.Images.Media.MIME_TYPE, IMAGE_TYPE); + Uri uri = listener.getSimpleActivity().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues); + intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); + } + listener + .getSimpleActivity() + .startActivityForResult(intent, TYPE_CAMERA); + } + + public void onActivityResult(int requestCode, int resultCode, Intent data) { + switch (resultCode) { + case Activity.RESULT_CANCELED: + listener.onCropCancel(); + break; + case UCrop.RESULT_ERROR: + if (data != null) { + Throwable cropError = UCrop.getError(data); + if (cropError != null) { + listener.onCropError(cropError.getMessage()); + } else { + listener.onCropError("裁剪出现未知错误"); + } + } else { + listener.onCropError("获取相册图片出现错误"); + } + break; + + case Activity.RESULT_OK: + switch (requestCode) { + case TYPE_CAMERA: + notifyImageToCamera(listener.getSimpleActivity(), imagePath); + UCrop of = UCrop.of(imagePath, Uri.fromFile(getDiskCacheDir())); + of.start(listener.getSimpleActivity()); + break; + case UCrop.REQUEST_CROP: + listener.onCropSuccess(UCrop.getOutput(data)); + break; + } + break; + } + } + + private File getDiskCacheDir() { + String cachePath; + if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) || !Environment.isExternalStorageRemovable()) { + File externalCacheDir = listener.getSimpleActivity().getExternalCacheDir(); + if (externalCacheDir != null) { + cachePath = externalCacheDir.getPath(); + } else { + cachePath = listener.getSimpleActivity().getCacheDir().getPath(); + } + } else { + cachePath = listener.getSimpleActivity().getCacheDir().getPath(); + } + return new File(cachePath, imageName()); + } + + private void notifyImageToCamera(Context context, Uri uri) { + try { + File file = new File(uri.getPath()); + MediaStore.Images.Media.insertImage(context.getContentResolver(), file.getAbsolutePath(), file.getName(), null); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri)); + } + + private String imageName() { + return System.currentTimeMillis() + ".jpg"; + } + + + public interface RxGalleryFinalCropListener { + + @NonNull + Activity getSimpleActivity(); + + + /** + * 裁剪被取消 + */ + void onCropCancel(); + + /** + * 裁剪成功 + * + * @param uri 裁剪的 Uri , 有可能会为Null + */ + void onCropSuccess(@Nullable Uri uri); + + + /** + * 裁剪失败 + * + * @param errorMessage 错误信息 + */ + void onCropError(@NonNull String errorMessage); + + } +} diff --git a/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/imageloader/ImageLoaderActivity.java b/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/imageloader/ImageLoaderActivity.java new file mode 100644 index 00000000..4b73bc00 --- /dev/null +++ b/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/imageloader/ImageLoaderActivity.java @@ -0,0 +1,86 @@ +package cn.finalteam.rxgalleryfinal.sample.imageloader; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.AppCompatCheckBox; +import android.view.View; +import android.widget.Toast; + +import cn.finalteam.rxgalleryfinal.RxGalleryFinal; +import cn.finalteam.rxgalleryfinal.imageloader.ImageLoaderType; +import cn.finalteam.rxgalleryfinal.rxbus.RxBusResultDisposable; +import cn.finalteam.rxgalleryfinal.rxbus.event.ImageRadioResultEvent; +import cn.finalteam.rxgalleryfinal.sample.R; +import cn.finalteam.rxgalleryfinal.utils.Logger; + +/** + * by y on 2017/6/7. + */ + +public class ImageLoaderActivity extends AppCompatActivity { + + private AppCompatCheckBox appCompatCheckBox; + private RxGalleryFinal with; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_imageloader); + appCompatCheckBox = (AppCompatCheckBox) findViewById(R.id.cb_gif); + findViewById(R.id.btn_glide).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + start(ImageLoaderType.GLIDE); + } + }); + findViewById(R.id.btn_picasso).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + start(ImageLoaderType.PICASSO); + } + }); + findViewById(R.id.btn_fresco).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + start(ImageLoaderType.FRESCO); + } + }); + findViewById(R.id.btn_universal).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + start(ImageLoaderType.UNIVERSAL); + } + }); + } + + private void start(ImageLoaderType imageLoaderType) { + switch (imageLoaderType) { + case PICASSO: + case UNIVERSAL: + Toast.makeText(getApplicationContext(), imageLoaderType + "不支持Gif", Toast.LENGTH_SHORT).show(); + break; + } + if (with == null) + with = RxGalleryFinal.with(this); + with.image() + .radio() + .gif(appCompatCheckBox.isChecked()) + .imageLoader(imageLoaderType) + .subscribe(new RxBusResultDisposable() { + @Override + protected void onEvent(ImageRadioResultEvent imageRadioResultEvent) throws Exception { + Toast.makeText(getBaseContext(), "选中了图片路径:" + imageRadioResultEvent.getResult().getOriginalPath(), Toast.LENGTH_SHORT).show(); + } + }).openGallery(); + } + + @Override + protected void onDestroy() { + if (with != null) { + Logger.i("RxGalleryFinal == null"); + with = null; + } + super.onDestroy(); + } +} diff --git a/sample/src/main/res/AndroidManifest.xml b/sample/src/main/res/AndroidManifest.xml new file mode 100644 index 00000000..2c611e14 --- /dev/null +++ b/sample/src/main/res/AndroidManifest.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sample/src/main/res/layout/activity_imageloader.xml b/sample/src/main/res/layout/activity_imageloader.xml new file mode 100644 index 00000000..68665157 --- /dev/null +++ b/sample/src/main/res/layout/activity_imageloader.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sample/src/main/res/layout/activity_main.xml b/sample/src/main/res/layout/activity_main.xml index c6c3804d..fb3ecace 100644 --- a/sample/src/main/res/layout/activity_main.xml +++ b/sample/src/main/res/layout/activity_main.xml @@ -3,38 +3,175 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" + android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" - android:orientation="vertical" tools:context="cn.finalteam.rxgalleryfinal.sample.MainActivity"> + + + + +