diff --git a/README.md b/README.md index 4fb5d636..c7bf8e35 100644 --- a/README.md +++ b/README.md @@ -25,15 +25,21 @@ RxGalleryFinal是一个android图片/视频文件选择器。其支持多选、 * 添加权限 ```xml - - + + + + + + ``` * 注册activity ```xml + signing.signPom(deployment) } + + repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { + authentication(userName: ossrhUsername, password: ossrhPassword) + } + + snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") { + authentication(userName: ossrhUsername, password: ossrhPassword) + } + + pom.groupId = PUBLISH_GROUP_ID + pom.artifactId = PUBLISH_ARTIFACT_ID + pom.version = PUBLISH_VERSION + + pom.project { + name 'RxCustomizedImagePicker' + packaging 'aar' //我这里发布的是安卓的包,所以写的aar + // optionally artifactId can be defined here + description 'Android image picker with support for camera, video compression, multiple images and cropping' + url 'https://github.com/shijingsh/RxGalleryFinal' + + scm { + connection 'https://github.com/shijingsh/RxGalleryFinal' + developerConnection 'scm:git:git@github.com:shijingsh/RxGalleryFinal.git' + url 'https://github.com/shijingsh' + } - // Set your license licenses { license { - name 'The Apache Software License, Version 2.0' + name 'The Apache License, Version 2.0' url 'http://www.apache.org/licenses/LICENSE-2.0.txt' } } + developers { developer { - id 'pengjianbo' - name 'pengjianbo' - email '172340021@qq.com' + id 'liukefu' + name 'liukefu' + email 'liukefu2050@sina.com' } } - scm { - connection gitUrl - developerConnection gitUrl - url siteUrl - - } } } } } +//===================================upload jcenter================================================= +/* +def siteUrl = 'https://github.com/liukefu2050/RxGalleryFinal' +def gitUrl = 'https://github.com/liukefu2050/RxGalleryFinal.git' + +group = "com.mg.RxCustomizedImagePicker" +version = "1.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 1.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 "1.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() @@ -109,15 +214,21 @@ bintray { configurations = ['archives'] pkg { repo = "maven" - name = "RxGalleryFinal" + name = "RxCustomizedImagePicker" + userOrg = user websiteUrl = siteUrl vcsUrl = gitUrl licenses = ["Apache-2.0"] publish = true version { + name = '1.0.3' + desc = 'android gallery' + released = new Date() + vcsTag = '1.0.3' + 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/androidTest/java/cn/finalteam/rxgalleryfinal/ApplicationTest.java b/library/src/androidTest/java/cn/finalteam/rxgalleryfinal/ApplicationTest.java deleted file mode 100644 index 8fc950dc..00000000 --- a/library/src/androidTest/java/cn/finalteam/rxgalleryfinal/ApplicationTest.java +++ /dev/null @@ -1,15 +0,0 @@ -package cn.finalteam.rxgalleryfinal; - -import android.app.Application; -import android.test.ApplicationTestCase; - -/** - * Testing Fundamentals - */ -public class ApplicationTest extends ApplicationTestCase { - public ApplicationTest() { - super(Application.class); - } - - -} \ No newline at end of file diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/Configuration.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/Configuration.java index 7d9438e8..30cc925e 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/Configuration.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/Configuration.java @@ -4,7 +4,7 @@ import android.graphics.Bitmap; import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.IntRange; +import androidx.annotation.IntRange; import com.yalantis.ucrop.UCropActivity; import com.yalantis.ucrop.model.AspectRatio; @@ -22,32 +22,46 @@ /** * Desction:配置信息 - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/5/7 下午3:58 */ -public class Configuration implements Parcelable{ +public class Configuration implements Parcelable { - protected Configuration() { - } + public static final Creator CREATOR = new Creator() { + @Override + public Configuration createFromParcel(Parcel in) { + return new Configuration(in); + } + @Override + public Configuration[] newArray(int size) { + return new Configuration[size]; + } + }; private boolean image = true; + private boolean isSelectBoth = false; private Context context; private List selectedList; private boolean radio; private boolean crop; private int maxSize = 1; + private boolean multiple = false; private int imageLoaderType; private int imageConfig; private boolean hideCamera; + private int videoQuality = 1; + private boolean isPlayGif; + private boolean hidePreview; + private boolean isVideoPreview; //==========UCrop START========== //是否隐藏裁剪页面底部控制栏,默认显示 private boolean hideBottomControls; //图片压缩质量,默认不压缩 - private int compressionQuality = 90; + private int compressionQuality = 100; //手势方式,默认all - private int []gestures; + private int[] gestures; //设置图片最大值,默认根据屏幕得出 private int maxBitmapSize = CropImageView.DEFAULT_MAX_BITMAP_SIZE; //设置最大缩放值,默认10.f @@ -58,15 +72,24 @@ protected Configuration() { //等比缩放默认值索引,默认原图比例 private int selectedByDefault; //等比缩放值表,默认1:1,3:4,原图比例,3:2,16:9 - private AspectRatio []aspectRatio; + private AspectRatio[] aspectRatio; //是否允许改变裁剪大小 - private boolean freestyleCropEnabled = OverlayView.DEFAULT_FREESTYLE_CROP_ENABLED; + private boolean freestyleCropEnabled = true; //是否显示裁剪框半透明椭圆浮层 - private boolean ovalDimmedLayer = OverlayView.DEFAULT_OVAL_DIMMED_LAYER; + private boolean ovalDimmedLayer = OverlayView.DEFAULT_CIRCLE_DIMMED_LAYER;//DEFAULT_OVAL_DIMMED_LAYER private int maxResultWidth; private int maxResultHeight; //==========UCrop END========== + //设置显示标题 + private String title = null; + private boolean openCameraOnStart = false; + private boolean returnAfterShot = false; + private boolean multipleShot = false; + + private int spanCount = 3; + protected Configuration() { + } protected Configuration(Parcel in) { image = in.readByte() != 0; @@ -74,6 +97,8 @@ protected Configuration(Parcel in) { radio = in.readByte() != 0; crop = in.readByte() != 0; maxSize = in.readInt(); + multiple = in.readByte() != 0; + videoQuality = in.readInt(); hideBottomControls = in.readByte() != 0; compressionQuality = in.readInt(); gestures = in.createIntArray(); @@ -90,19 +115,32 @@ protected Configuration(Parcel in) { imageLoaderType = in.readInt(); imageConfig = in.readInt(); hideCamera = in.readByte() != 0; + isPlayGif = in.readByte() != 0; + hidePreview = in.readByte() != 0; + isVideoPreview = in.readByte() != 0; + title = in.readString(); + openCameraOnStart = in.readByte() != 0; + returnAfterShot = in.readByte() != 0; + multipleShot = in.readByte() != 0; + spanCount = in.readInt(); + isSelectBoth = in.readByte() != 0; } - public static final Creator CREATOR = new Creator() { - @Override - public Configuration createFromParcel(Parcel in) { - return new Configuration(in); - } + public boolean isHidePreview() { + return hidePreview; + } - @Override - public Configuration[] newArray(int size) { - return new Configuration[size]; - } - }; + public void setHidePreview(boolean hidePreview) { + this.hidePreview = hidePreview; + } + + public boolean isPlayGif() { + return isPlayGif; + } + + public void setPlayGif(boolean playGif) { + isPlayGif = playGif; + } public boolean isImage() { return image; @@ -112,6 +150,14 @@ protected void setImage(boolean image) { this.image = image; } + public boolean isSelectBoth() { + return isSelectBoth; + } + + public void setSelectBoth(boolean selectBoth) { + isSelectBoth = selectBoth; + } + public Context getContext() { return context; } @@ -144,6 +190,22 @@ protected void setMaxSize(int maxSize) { this.maxSize = maxSize; } + public boolean isMultiple() { + return multiple; + } + + public void setMultiple(boolean multiple) { + this.multiple = multiple; + } + + public int getVideoQuality() { + return videoQuality; + } + + public void setVideoQuality(int videoQuality) { + this.videoQuality = videoQuality; + } + public boolean isHideCamera() { return hideCamera; } @@ -152,9 +214,41 @@ public void setHideCamera(boolean hideCamera) { this.hideCamera = hideCamera; } + //#ADD + public int getImageLoaderType() { + return imageLoaderType; + } + + protected void setImageLoaderType(int imageLoaderType) { + this.imageLoaderType = imageLoaderType; + } + public boolean isOpenCameraOnStart() { + return openCameraOnStart; + } + + public void setOpenCameraOnStart(boolean openCameraOnStart) { + this.openCameraOnStart = openCameraOnStart; + } + + public boolean isReturnAfterShot() { + return returnAfterShot; + } + + public void setReturnAfterShot(boolean returnAfterShot) { + this.returnAfterShot = returnAfterShot; + } + + public boolean isMultipleShot() { + return multipleShot; + } + + public void setMultipleShot(boolean multipleShot) { + this.multipleShot = multipleShot; + } + public AbsImageLoader getImageLoader() { AbsImageLoader imageLoader = null; - switch (imageLoaderType){ + switch (imageLoaderType) { case 1: imageLoader = new PicassoImageLoader(); break; @@ -167,19 +261,15 @@ public AbsImageLoader getImageLoader() { case 4: imageLoader = new UniversalImageLoader(); break; - case 5: - + default: + imageLoader = new GlideImageLoader(); break; } return imageLoader; } - protected void setImageLoaderType(int imageLoaderType) { - this.imageLoaderType = imageLoaderType; - } - public Bitmap.Config getImageConfig() { - switch (imageConfig){ + switch (imageConfig) { case 1: return Bitmap.Config.ALPHA_8; case 2: @@ -212,14 +302,14 @@ public void setCompressionQuality(int compressionQuality) { this.compressionQuality = compressionQuality; } - public void setAllowedGestures(@UCropActivity.GestureTypes int []gestures) { - this.gestures = gestures; - } - public int[] getAllowedGestures() { return gestures; } + public void setAllowedGestures(@UCropActivity.GestureTypes int[] gestures) { + this.gestures = gestures; + } + public int getMaxBitmapSize() { return maxBitmapSize; } @@ -322,6 +412,8 @@ public void writeToParcel(Parcel parcel, int i) { parcel.writeByte((byte) (radio ? 1 : 0)); parcel.writeByte((byte) (crop ? 1 : 0)); parcel.writeInt(maxSize); + parcel.writeByte((byte) (multiple ? 1 : 0)); + parcel.writeInt(videoQuality); parcel.writeByte((byte) (hideBottomControls ? 1 : 0)); parcel.writeInt(compressionQuality); parcel.writeIntArray(gestures); @@ -338,5 +430,41 @@ public void writeToParcel(Parcel parcel, int i) { parcel.writeInt(imageLoaderType); parcel.writeInt(imageConfig); parcel.writeByte((byte) (hideCamera ? 1 : 0)); + parcel.writeByte((byte) (isPlayGif ? 1 : 0)); + parcel.writeByte((byte) (hidePreview ? 1 : 0)); + parcel.writeByte((byte) (isVideoPreview ? 1 : 0)); + parcel.writeString(title); + parcel.writeByte((byte) (openCameraOnStart ? 1 : 0)); + parcel.writeByte((byte) (returnAfterShot ? 1 : 0)); + parcel.writeByte((byte) (multipleShot ? 1 : 0)); + parcel.writeInt(spanCount); + parcel.writeByte((byte) (isSelectBoth ? 1 : 0)); + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public boolean isVideoPreview() { + return isVideoPreview; + } + + public int getSpanCount() { + if(spanCount <= 0){ + return 3; + } + return spanCount; + } + + public void setSpanCount(int spanCount) { + this.spanCount = spanCount; + } + + public void setVideoPreview(boolean videoPreview) { + isVideoPreview = videoPreview; } } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/RxGalleryFinal.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/RxGalleryFinal.java index 352598de..c901dfff 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/RxGalleryFinal.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/RxGalleryFinal.java @@ -4,9 +4,9 @@ import android.content.Intent; import android.graphics.Bitmap; import android.os.Bundle; -import android.support.annotation.FloatRange; -import android.support.annotation.IntRange; -import android.support.annotation.NonNull; +import androidx.annotation.FloatRange; +import androidx.annotation.IntRange; +import androidx.annotation.NonNull; import android.widget.Toast; import com.yalantis.ucrop.UCropActivity; @@ -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; } @@ -54,13 +55,36 @@ public RxGalleryFinal video() { configuration.setImage(false); return this; } - + public RxGalleryFinal selectBoth() { + configuration.setSelectBoth(true); + return this; + } // public RxGalleryFinal filterMime(MediaType ...mediaTypes) { // configuration.setFilterMimes(mediaTypes); // 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 +94,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; } @@ -85,9 +114,46 @@ public RxGalleryFinal selected(@NonNull List list) { return this; } + /** + * 设置显示标题 + * @return + */ + public RxGalleryFinal setTitle(String title) { + configuration.setTitle(title); + return this; + } + /** + * 直接打开相机 + * @return + */ + public RxGalleryFinal openCameraOnStart() { + configuration.setOpenCameraOnStart(true); + return this; + } + + /** + * 拍摄后,直接返回图片 + * @return + */ + public RxGalleryFinal returnAfterShot() { + configuration.setReturnAfterShot(true); + return this; + } + /** + * 打开相机后,多次拍摄图片 + * @return + */ + public RxGalleryFinal multipleShot() { + configuration.setMultipleShot(true); + return this; + } + public RxGalleryFinal spanCount(@IntRange(from = 1) int spanCount) { + configuration.setSpanCount(spanCount); + return this; + } public RxGalleryFinal imageConfig(@NonNull Bitmap.Config config) { int c = 3; - switch (config){ + switch (config) { case ALPHA_8: c = 1; break; @@ -101,21 +167,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 +188,6 @@ public RxGalleryFinal imageLoader(@NonNull ImageLoaderType imageLoaderType) { /** * 隐藏相机 - * @return */ public RxGalleryFinal hideCamera() { configuration.setHideCamera(true); @@ -133,8 +196,6 @@ public RxGalleryFinal hideCamera() { /** * set to true to hide the bottom controls (shown by default) - * @param hide - * @return */ public RxGalleryFinal cropHideBottomControls(boolean hide) { configuration.setHideBottomControls(hide); @@ -143,22 +204,23 @@ 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); return this; } + public RxGalleryFinal setVideoQuality(int videoQuality){ + configuration.setVideoQuality(videoQuality); + return this; + } + /** * 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; } @@ -220,7 +282,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); @@ -229,7 +290,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); @@ -238,8 +298,6 @@ 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); @@ -248,48 +306,50 @@ public RxGalleryFinal cropMaxResultSize(@IntRange(from = 100) int width, @IntRan /** * 设置回调 - * @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); @@ -299,4 +359,5 @@ private void execute() { context.startActivity(intent); } + } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/anim/Animation.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/anim/Animation.java index 01d2c949..2dde7643 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/anim/Animation.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/anim/Animation.java @@ -4,26 +4,23 @@ /** * The parent class of all animation classes. - * */ public abstract class Animation { - // constants - public static final int DIRECTION_LEFT = 1; - public static final int DIRECTION_RIGHT = 2; - public static final int DIRECTION_UP = 3; - public static final int DIRECTION_DOWN = 4; + public static final int DIRECTION_DOWN = 4; + public static final int DURATION_DEFAULT = 300; // 300 ms + // constants + static final int DIRECTION_LEFT = 1; + static final int DIRECTION_RIGHT = 2; + static final int DIRECTION_UP = 3; + static final int DURATION_LONG = 500; // 500 ms - public static final int DURATION_DEFAULT = 300; // 300 ms - public static final int DURATION_SHORT = 100; // 100 ms - public static final int DURATION_LONG = 500; // 500 ms + View view; - View view; - - /** - * This method animates the properties of the view specific to the Animation - * object. - */ - public abstract void animate(); + /** + * This method animates the properties of the view specific to the Animation + * object. + */ + public abstract void animate(); } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/anim/AnimationListener.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/anim/AnimationListener.java index 2c0ae97b..dfda739f 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/anim/AnimationListener.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/anim/AnimationListener.java @@ -2,18 +2,16 @@ /** * This interface is a custom listener to determine the end of an animation. - * + * * @author Phu - * */ public interface AnimationListener { - /** - * This method is called when the animation ends. - * - * @param animation - * The Animation object. - */ - public void onAnimationEnd(Animation animation); + /** + * This method is called when the animation ends. + * + * @param animation The Animation object. + */ + void onAnimationEnd(Animation animation); } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/anim/Combinable.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/anim/Combinable.java deleted file mode 100644 index 164acebf..00000000 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/anim/Combinable.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.finalteam.rxgalleryfinal.anim; - -import android.animation.AnimatorSet; -import android.animation.TimeInterpolator; - -/** - * This interface is implemented only by animation classes that can be combined - * to animate together. - * - */ -public interface Combinable { - - public void animate(); - public AnimatorSet getAnimatorSet(); - public Animation setInterpolator(TimeInterpolator interpolator); - public long getDuration(); - public Animation setDuration(long duration); - public Animation setListener(AnimationListener listener); - -} diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/anim/SlideInUnderneathAnimation.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/anim/SlideInUnderneathAnimation.java index 9deeebed..1de5e715 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/anim/SlideInUnderneathAnimation.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/anim/SlideInUnderneathAnimation.java @@ -12,172 +12,169 @@ /** * This animation causes the view to slide in underneath from its own borders. - * + * * @author SiYao - * */ @TargetApi(14) public class SlideInUnderneathAnimation extends Animation { - int direction; - TimeInterpolator interpolator; - long duration; - AnimationListener listener; - - /** - * This animation causes the view to slide in underneath from its own - * borders. - * - * @param view - * The view to be animated. - */ - public SlideInUnderneathAnimation(View view) { - this.view = view; - direction = DIRECTION_LEFT; - interpolator = new AccelerateDecelerateInterpolator(); - duration = DURATION_LONG; - listener = null; - } - - @Override - public void animate() { - final ViewGroup parentView = (ViewGroup) view.getParent(); - final FrameLayout slideInFrame = new FrameLayout(view.getContext()); - final int positionView = parentView.indexOfChild(view); - slideInFrame.setLayoutParams(view.getLayoutParams()); - slideInFrame.setClipChildren(true); - parentView.removeView(view); - slideInFrame.addView(view); - parentView.addView(slideInFrame, positionView); - - ObjectAnimator slideInAnim = null; - float viewWidth = view.getWidth(), viewHeight = view.getHeight(); - switch (direction) { - case DIRECTION_LEFT: - view.setTranslationX(-viewWidth); - slideInAnim = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, - slideInFrame.getX()); - break; - case DIRECTION_RIGHT: - view.setTranslationX(viewWidth); - slideInAnim = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, - slideInFrame.getX()); - break; - case DIRECTION_UP: - view.setTranslationY(-viewHeight); - slideInAnim = ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, - slideInFrame.getY()); - break; - case DIRECTION_DOWN: - view.setTranslationY(viewHeight); - slideInAnim = ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, - slideInFrame.getY()); - break; - default: - break; - } - slideInAnim.setInterpolator(interpolator); - slideInAnim.setDuration(duration); - slideInAnim.addListener(new AnimatorListenerAdapter() { - - @Override - public void onAnimationStart(Animator animation) { - view.setVisibility(View.VISIBLE); - } - - @Override - public void onAnimationEnd(Animator animation) { - slideInFrame.removeAllViews(); - view.setLayoutParams(slideInFrame.getLayoutParams()); - parentView.addView(view, positionView); - if (getListener() != null) { - getListener().onAnimationEnd( - SlideInUnderneathAnimation.this); - } - } - }); - slideInAnim.start(); - } - - /** - * The available directions to slide in from are DIRECTION_LEFT - * , DIRECTION_RIGHT, DIRECTION_TOP and - * DIRECTION_BOTTOM. - * - * @return The direction to slide the view in from. - * @see Animation - */ - public int getDirection() { - return direction; - } - - /** - * The available directions to slide in from are DIRECTION_LEFT - * , DIRECTION_RIGHT, DIRECTION_TOP and - * DIRECTION_BOTTOM. - * - * @param direction - * The direction to set to slide the view in from. - * @return This object, allowing calls to methods in this class to be - * chained. - * @see Animation - */ - public SlideInUnderneathAnimation setDirection(int direction) { - this.direction = direction; - return this; - } - - /** - * @return The interpolator of the entire animation. - */ - public TimeInterpolator getInterpolator() { - return interpolator; - } - - /** - * @param interpolator - * The interpolator of the entire animation to set. - */ - public SlideInUnderneathAnimation setInterpolator( - TimeInterpolator interpolator) { - this.interpolator = interpolator; - return this; - } - - /** - * @return The duration of the entire animation. - */ - public long getDuration() { - return duration; - } - - /** - * @param duration - * The duration of the entire animation to set. - * @return This object, allowing calls to methods in this class to be - * chained. - */ - public SlideInUnderneathAnimation setDuration(long duration) { - this.duration = duration; - return this; - } - - /** - * @return The listener for the end of the animation. - */ - public AnimationListener getListener() { - return listener; - } - - /** - * @param listener - * The listener to set for the end of the animation. - * @return This object, allowing calls to methods in this class to be - * chained. - */ - public SlideInUnderneathAnimation setListener(AnimationListener listener) { - this.listener = listener; - return this; - } + private int direction; + private TimeInterpolator interpolator; + private long duration; + private AnimationListener listener; + + /** + * This animation causes the view to slide in underneath from its own + * borders. + * + * @param view The view to be animated. + */ + public SlideInUnderneathAnimation(View view) { + this.view = view; + direction = DIRECTION_LEFT; + interpolator = new AccelerateDecelerateInterpolator(); + duration = DURATION_LONG; + listener = null; + } + + @Override + public void animate() { + final ViewGroup parentView = (ViewGroup) view.getParent(); + final FrameLayout slideInFrame = new FrameLayout(view.getContext()); + final int positionView = parentView.indexOfChild(view); + slideInFrame.setLayoutParams(view.getLayoutParams()); + slideInFrame.setClipChildren(true); + parentView.removeView(view); + slideInFrame.addView(view); + parentView.addView(slideInFrame, positionView); + + ObjectAnimator slideInAnim = null; + float viewWidth = view.getWidth(), viewHeight = view.getHeight(); + switch (direction) { + case DIRECTION_LEFT: + view.setTranslationX(-viewWidth); + slideInAnim = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, + slideInFrame.getX()); + break; + case DIRECTION_RIGHT: + view.setTranslationX(viewWidth); + slideInAnim = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, + slideInFrame.getX()); + break; + case DIRECTION_UP: + view.setTranslationY(-viewHeight); + slideInAnim = ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, + slideInFrame.getY()); + break; + case DIRECTION_DOWN: + view.setTranslationY(viewHeight); + slideInAnim = ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, + slideInFrame.getY()); + break; + default: + break; + } + if (slideInAnim == null) { + return; + } + slideInAnim.setInterpolator(interpolator); + slideInAnim.setDuration(duration); + slideInAnim.addListener(new AnimatorListenerAdapter() { + + @Override + public void onAnimationStart(Animator animation) { + view.setVisibility(View.VISIBLE); + } + + @Override + public void onAnimationEnd(Animator animation) { + slideInFrame.removeAllViews(); + view.setLayoutParams(slideInFrame.getLayoutParams()); + parentView.addView(view, positionView); + if (getListener() != null) { + getListener().onAnimationEnd( + SlideInUnderneathAnimation.this); + } + } + }); + slideInAnim.start(); + } + + /** + * The available directions to slide in from are DIRECTION_LEFT + * , DIRECTION_RIGHT, DIRECTION_TOP and + * DIRECTION_BOTTOM. + * + * @return The direction to slide the view in from. + * @see Animation + */ + public int getDirection() { + return direction; + } + + /** + * The available directions to slide in from are DIRECTION_LEFT + * , DIRECTION_RIGHT, DIRECTION_TOP and + * DIRECTION_BOTTOM. + * + * @param direction The direction to set to slide the view in from. + * @return This object, allowing calls to methods in this class to be + * chained. + * @see Animation + */ + public SlideInUnderneathAnimation setDirection(int direction) { + this.direction = direction; + return this; + } + + /** + * @return The interpolator of the entire animation. + */ + public TimeInterpolator getInterpolator() { + return interpolator; + } + + /** + * @param interpolator The interpolator of the entire animation to set. + */ + public SlideInUnderneathAnimation setInterpolator( + TimeInterpolator interpolator) { + this.interpolator = interpolator; + return this; + } + + /** + * @return The duration of the entire animation. + */ + public long getDuration() { + return duration; + } + + /** + * @param duration The duration of the entire animation to set. + * @return This object, allowing calls to methods in this class to be + * chained. + */ + public SlideInUnderneathAnimation setDuration(long duration) { + this.duration = duration; + return this; + } + + /** + * @return The listener for the end of the animation. + */ + private AnimationListener getListener() { + return listener; + } + + /** + * @param listener The listener to set for the end of the animation. + * @return This object, allowing calls to methods in this class to be + * chained. + */ + public SlideInUnderneathAnimation setListener(AnimationListener listener) { + this.listener = listener; + return this; + } } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/anim/SlideOutUnderneathAnimation.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/anim/SlideOutUnderneathAnimation.java index 9635a41d..98460386 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/anim/SlideOutUnderneathAnimation.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/anim/SlideOutUnderneathAnimation.java @@ -16,168 +16,162 @@ * This animation causes the view to slide out underneath to its own borders. On * animation end, the view is restored to its original state and is set to * View.INVISIBLE. - * + * * @author SiYao - * */ @TargetApi(14) public class SlideOutUnderneathAnimation extends Animation { - int direction; - TimeInterpolator interpolator; - long duration; - AnimationListener listener; - ValueAnimator slideAnim; - - /** - * This animation causes the view to slide out underneath to its own - * borders. On animation end, the view is restored to its original state and - * is set to View.INVISIBLE. - * - * @param view - * The view to be animated. - */ - public SlideOutUnderneathAnimation(View view) { - this.view = view; - direction = DIRECTION_LEFT; - interpolator = new AccelerateDecelerateInterpolator(); - duration = DURATION_LONG; - listener = null; - } - - @Override - public void animate() { - final ViewGroup parentView = (ViewGroup) view.getParent(); - final FrameLayout slideOutFrame = new FrameLayout(view.getContext()); - final int positionView = parentView.indexOfChild(view); - slideOutFrame.setLayoutParams(view.getLayoutParams()); - slideOutFrame.setClipChildren(true); - parentView.removeView(view); - slideOutFrame.addView(view); - parentView.addView(slideOutFrame, positionView); - - switch (direction) { - case DIRECTION_LEFT: - slideAnim = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, - view.getTranslationX() - view.getWidth()); - break; - case DIRECTION_RIGHT: - slideAnim = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, - view.getTranslationX() + view.getWidth()); - break; - case DIRECTION_UP: - slideAnim = ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, - view.getTranslationY() - view.getHeight()); - break; - case DIRECTION_DOWN: - slideAnim = ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, - view.getTranslationY() + view.getHeight()); - break; - default: - break; - } - - AnimatorSet slideSet = new AnimatorSet(); - slideSet.play(slideAnim); - slideSet.setInterpolator(interpolator); - slideSet.setDuration(duration); - slideSet.addListener(new AnimatorListenerAdapter() { - - @Override - public void onAnimationEnd(Animator animation) { - view.setVisibility(View.INVISIBLE); - slideAnim.reverse(); - slideOutFrame.removeAllViews(); - parentView.removeView(slideOutFrame); - parentView.addView(view, positionView); - if (getListener() != null) { - getListener().onAnimationEnd( - SlideOutUnderneathAnimation.this); - } - } - }); - slideSet.start(); - } - - /** - * The available directions to slide in from are DIRECTION_LEFT - * , DIRECTION_RIGHT, DIRECTION_TOP and - * DIRECTION_BOTTOM. - * - * @return The direction to slide the view out to. - * @see Animation - */ - public int getDirection() { - return direction; - } - - /** - * The available directions to slide in from are DIRECTION_LEFT - * , DIRECTION_RIGHT, DIRECTION_TOP and - * DIRECTION_BOTTOM. - * - * @param direction - * The direction to set to slide the view out to. - * @return This object, allowing calls to methods in this class to be - * chained. - * @see Animation - */ - public SlideOutUnderneathAnimation setDirection(int direction) { - this.direction = direction; - return this; - } - - /** - * @return The interpolator of the entire animation. - */ - public TimeInterpolator getInterpolator() { - return interpolator; - } - - /** - * @param interpolator - * The interpolator of the entire animation to set. - */ - public SlideOutUnderneathAnimation setInterpolator( - TimeInterpolator interpolator) { - this.interpolator = interpolator; - return this; - } - - /** - * @return The duration of the entire animation. - */ - public long getDuration() { - return duration; - } - - /** - * @param duration - * The duration of the entire animation to set. - * @return This object, allowing calls to methods in this class to be - * chained. - */ - public SlideOutUnderneathAnimation setDuration(long duration) { - this.duration = duration; - return this; - } - - /** - * @return The listener for the end of the animation. - */ - public AnimationListener getListener() { - return listener; - } - - /** - * @param listener - * The listener to set for the end of the animation. - * @return This object, allowing calls to methods in this class to be - * chained. - */ - public SlideOutUnderneathAnimation setListener(AnimationListener listener) { - this.listener = listener; - return this; - } + private int direction; + private TimeInterpolator interpolator; + private long duration; + private AnimationListener listener; + private ValueAnimator slideAnim; + + /** + * This animation causes the view to slide out underneath to its own + * borders. On animation end, the view is restored to its original state and + * is set to View.INVISIBLE. + * + * @param view The view to be animated. + */ + public SlideOutUnderneathAnimation(View view) { + this.view = view; + direction = DIRECTION_LEFT; + interpolator = new AccelerateDecelerateInterpolator(); + duration = DURATION_LONG; + listener = null; + } + + @Override + public void animate() { + final ViewGroup parentView = (ViewGroup) view.getParent(); + final FrameLayout slideOutFrame = new FrameLayout(view.getContext()); + final int positionView = parentView.indexOfChild(view); + slideOutFrame.setLayoutParams(view.getLayoutParams()); + slideOutFrame.setClipChildren(true); + parentView.removeView(view); + slideOutFrame.addView(view); + parentView.addView(slideOutFrame, positionView); + + switch (direction) { + case DIRECTION_LEFT: + slideAnim = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, + view.getTranslationX() - view.getWidth()); + break; + case DIRECTION_RIGHT: + slideAnim = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, + view.getTranslationX() + view.getWidth()); + break; + case DIRECTION_UP: + slideAnim = ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, + view.getTranslationY() - view.getHeight()); + break; + case DIRECTION_DOWN: + slideAnim = ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, + view.getTranslationY() + view.getHeight()); + break; + default: + break; + } + + AnimatorSet slideSet = new AnimatorSet(); + slideSet.play(slideAnim); + slideSet.setInterpolator(interpolator); + slideSet.setDuration(duration); + slideSet.addListener(new AnimatorListenerAdapter() { + + @Override + public void onAnimationEnd(Animator animation) { + view.setVisibility(View.INVISIBLE); + slideAnim.reverse(); + slideOutFrame.removeAllViews(); + parentView.removeView(slideOutFrame); + parentView.addView(view, positionView); + if (getListener() != null) { + getListener().onAnimationEnd( + SlideOutUnderneathAnimation.this); + } + } + }); + slideSet.start(); + } + + /** + * The available directions to slide in from are DIRECTION_LEFT + * , DIRECTION_RIGHT, DIRECTION_TOP and + * DIRECTION_BOTTOM. + * + * @return The direction to slide the view out to. + * @see Animation + */ + public int getDirection() { + return direction; + } + + /** + * The available directions to slide in from are DIRECTION_LEFT + * , DIRECTION_RIGHT, DIRECTION_TOP and + * DIRECTION_BOTTOM. + * + * @param direction The direction to set to slide the view out to. + * @return This object, allowing calls to methods in this class to be + * chained. + * @see Animation + */ + public SlideOutUnderneathAnimation setDirection(int direction) { + this.direction = direction; + return this; + } + + /** + * @return The interpolator of the entire animation. + */ + public TimeInterpolator getInterpolator() { + return interpolator; + } + + /** + * @param interpolator The interpolator of the entire animation to set. + */ + public SlideOutUnderneathAnimation setInterpolator( + TimeInterpolator interpolator) { + this.interpolator = interpolator; + return this; + } + + /** + * @return The duration of the entire animation. + */ + public long getDuration() { + return duration; + } + + /** + * @param duration The duration of the entire animation to set. + * @return This object, allowing calls to methods in this class to be + * chained. + */ + public SlideOutUnderneathAnimation setDuration(long duration) { + this.duration = duration; + return this; + } + + /** + * @return The listener for the end of the animation. + */ + private AnimationListener getListener() { + return listener; + } + + /** + * @param listener The listener to set for the end of the animation. + * @return This object, allowing calls to methods in this class to be + * chained. + */ + public SlideOutUnderneathAnimation setListener(AnimationListener listener) { + this.listener = listener; + return this; + } } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/bean/BucketBean.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/bean/BucketBean.java index ab2d614d..d0549516 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/bean/BucketBean.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/bean/BucketBean.java @@ -4,7 +4,7 @@ /** * Desction:文件夹信息 - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/6/9 下午2:47 */ public class BucketBean { @@ -40,7 +40,7 @@ public void setImageCount(int imageCount) { } public String getCover() { - if(cover == null){ + if (cover == null) { return ""; } return cover; @@ -60,7 +60,7 @@ public void setOrientation(int orientation) { @Override public boolean equals(Object o) { - if(o == null || !(o instanceof BucketBean)) { + if (o == null || !(o instanceof BucketBean)) { return false; } BucketBean bucketBean = (BucketBean) o; diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/bean/ImageCropBean.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/bean/ImageCropBean.java index e99b3b23..8cd37e44 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/bean/ImageCropBean.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/bean/ImageCropBean.java @@ -5,16 +5,28 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/8/1 下午10:27 */ public class ImageCropBean extends MediaBean implements Parcelable { + public static final Creator CREATOR = new Creator() { + @Override + public ImageCropBean createFromParcel(Parcel in) { + return new ImageCropBean(in); + } + + @Override + public ImageCropBean[] newArray(int size) { + return new ImageCropBean[size]; + } + }; private String cropPath; private float aspectRatio; - public ImageCropBean(){} + public ImageCropBean() { + } - protected ImageCropBean(Parcel in) { + private ImageCropBean(Parcel in) { super(in); cropPath = in.readString(); aspectRatio = in.readFloat(); @@ -32,18 +44,6 @@ public int describeContents() { return 0; } - public static final Creator CREATOR = new Creator() { - @Override - public ImageCropBean createFromParcel(Parcel in) { - return new ImageCropBean(in); - } - - @Override - public ImageCropBean[] newArray(int size) { - return new ImageCropBean[size]; - } - }; - public String getCropPath() { return cropPath; } @@ -60,8 +60,8 @@ public void setAspectRatio(float aspectRatio) { this.aspectRatio = aspectRatio; } - public void copyMediaBean(MediaBean mediaBean){ - if(mediaBean != null){ + public void copyMediaBean(MediaBean mediaBean) { + if (mediaBean != null) { setId(mediaBean.getId()); setTitle(mediaBean.getTitle()); setOriginalPath(mediaBean.getOriginalPath()); diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/bean/MediaBean.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/bean/MediaBean.java index 0739e28a..c39df96c 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/bean/MediaBean.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/bean/MediaBean.java @@ -7,14 +7,24 @@ /** * Desction:Media Bean - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/5/4 下午4:14 */ public class MediaBean implements Parcelable { + public static final Creator CREATOR = new Creator() { + @Override + public MediaBean createFromParcel(Parcel in) { + return new MediaBean(in); + } + + @Override + public MediaBean[] newArray(int size) { + return new MediaBean[size]; + } + }; //图片ID private long id; - private String title; //图片、视频源地址 private String originalPath; @@ -36,19 +46,18 @@ public class MediaBean implements Parcelable { private int orientation; //文件大小 private long length; - //文件夹相关 private String bucketId; private String bucketDisplayName; - //大缩略图 private String thumbnailBigPath; //小缩略图 private String thumbnailSmallPath; - public MediaBean(){} + public MediaBean() { + } - protected MediaBean(Parcel in) { + MediaBean(Parcel in) { id = in.readLong(); title = in.readString(); originalPath = in.readString(); @@ -92,18 +101,6 @@ public int describeContents() { return 0; } - public static final Creator CREATOR = new Creator() { - @Override - public MediaBean createFromParcel(Parcel in) { - return new MediaBean(in); - } - - @Override - public MediaBean[] newArray(int size) { - return new MediaBean[size]; - } - }; - public long getId() { return id; } @@ -169,7 +166,7 @@ public void setBucketDisplayName(String bucketDisplayName) { } public String getThumbnailBigPath() { - if(new File(thumbnailBigPath).exists()) { + if (new File(thumbnailBigPath).exists()) { return thumbnailBigPath; } return ""; @@ -180,7 +177,7 @@ public void setThumbnailBigPath(String thumbnailBigPath) { } public String getThumbnailSmallPath() { - if(new File(thumbnailSmallPath).exists()) { + if (new File(thumbnailSmallPath).exists()) { return thumbnailSmallPath; } return ""; @@ -240,16 +237,13 @@ public void setLength(long length) { @Override public boolean equals(Object obj) { - if(obj == null || !(obj instanceof MediaBean)){ + if (obj == null || !(obj instanceof MediaBean)) { return false; } MediaBean bean = (MediaBean) obj; - if(bean == null){ - return false; - } - return bean.getId() == getId(); + } @Override diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/exception/UnknownImageLoaderTypeException.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/exception/UnknownImageLoaderTypeException.java deleted file mode 100644 index 7b84a0c6..00000000 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/exception/UnknownImageLoaderTypeException.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.finalteam.rxgalleryfinal.exception; - -/** - * Desction: - * Author:pengjianbo - * Date:16/8/9 上午7:50 - */ -public class UnknownImageLoaderTypeException extends RuntimeException { - - public UnknownImageLoaderTypeException(){ - super("未知的ImageLoader"); - } - - public UnknownImageLoaderTypeException(String errormsg){ - super(errormsg); - } -} diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/exception/package-info.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/exception/package-info.java deleted file mode 100644 index 80a80edb..00000000 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/exception/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * exception包 - */ -package cn.finalteam.rxgalleryfinal.exception; \ 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..760f1ad7 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 @@ -82,8 +113,8 @@ public boolean onTouchEvent(MotionEvent event) { .path(path) .build(); ImageRequestBuilder builder = ImageRequestBuilder.newBuilderWithSource(uri) - .setAutoRotateEnabled(true); - if(resize){ + .setRotationOptions(RotationOptions.autoRotate()); + 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/imageloader/rotate/RotateTransformation.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/imageloader/rotate/RotateTransformation.java index 77e82367..f7257dfc 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/imageloader/rotate/RotateTransformation.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/imageloader/rotate/RotateTransformation.java @@ -8,7 +8,7 @@ import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; /** - * Created by pengjianbo on 2016/8/16 0016. + * Created by pengjianbo Dujinyang on 2016/8/16 0016. */ public class RotateTransformation extends BitmapTransformation { 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..8f0171c2 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); + void generateMeidas(String bucketId, int page, int limit,boolean isImage); + + 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..c4f9c146 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,56 +7,55 @@ 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; public MediaSrcFactoryInteractorImpl(Context context, boolean isImage, OnGenerateMediaListener onGenerateMediaListener) { this.context = context; - this.isImage = isImage; this.onGenerateMediaListener = onGenerateMediaListener; } @Override - public void generateMeidas(final String bucketId, final int page, final int limit) { - Observable.create((Observable.OnSubscribe>) subscriber -> { + public void generateMeidas(final String bucketId, final int page, final int limit,boolean isImage) { + 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/presenter/ActivityFragmentPresenter.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/presenter/ActivityFragmentPresenter.java deleted file mode 100644 index 9fbb49c7..00000000 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/presenter/ActivityFragmentPresenter.java +++ /dev/null @@ -1,9 +0,0 @@ -package cn.finalteam.rxgalleryfinal.presenter; - -/** - * Desction:activity fragment presenter - * Author:pengjianbo - * Date:16/5/14 下午11:12 - */ -public interface ActivityFragmentPresenter { -} diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/presenter/MediaGridPresenter.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/presenter/MediaGridPresenter.java index 11fe3db6..eadf876a 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/presenter/MediaGridPresenter.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/presenter/MediaGridPresenter.java @@ -4,12 +4,14 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/5/14 上午10:53 */ public interface MediaGridPresenter { void setMediaGridView(MediaGridView mediaGridView); - void getMediaList(String bucketId, int pageSize, int currentOffset); + + void getMediaList(String bucketId, int pageSize, int currentOffset,boolean isImage); + void getBucketList(); } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/presenter/impl/ActivityFragmentPresenterImpl.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/presenter/impl/ActivityFragmentPresenterImpl.java deleted file mode 100644 index 50b4c6a6..00000000 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/presenter/impl/ActivityFragmentPresenterImpl.java +++ /dev/null @@ -1,11 +0,0 @@ -package cn.finalteam.rxgalleryfinal.presenter.impl; - -import cn.finalteam.rxgalleryfinal.presenter.ActivityFragmentPresenter; - -/** - * Desction: - * Author:pengjianbo - * Date:16/5/14 下午11:16 - */ -public class ActivityFragmentPresenterImpl implements ActivityFragmentPresenter { -} diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/presenter/impl/MediaGridPresenterImpl.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/presenter/impl/MediaGridPresenterImpl.java index ca5a7d40..3e1f979c 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/presenter/impl/MediaGridPresenterImpl.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/presenter/impl/MediaGridPresenterImpl.java @@ -15,27 +15,24 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/5/14 上午10:58 */ public class MediaGridPresenterImpl implements MediaGridPresenter, MediaSrcFactoryInteractor.OnGenerateMediaListener, - MediaBucketFactoryInteractor.OnGenerateBucketListener{ + MediaBucketFactoryInteractor.OnGenerateBucketListener { - MediaSrcFactoryInteractor mediaSrcFactoryInteractor; - MediaBucketFactoryInteractor mediaBucketFactoryInteractor; + private final MediaSrcFactoryInteractor mediaSrcFactoryInteractor; + private final MediaBucketFactoryInteractor mediaBucketFactoryInteractor; - Context context; - MediaGridView mediaGridView; + private MediaGridView mediaGridView; public MediaGridPresenterImpl(Context context, boolean isImage) { - this.context = context; this.mediaSrcFactoryInteractor = new MediaSrcFactoryInteractorImpl(context, isImage, this); this.mediaBucketFactoryInteractor = new MediaBucketFactoryInteractorImpl(context, isImage, this); } /** * 设置MVP view(操作UI接口) - * @param mediaGridView */ @Override public void setMediaGridView(MediaGridView mediaGridView) { @@ -44,13 +41,10 @@ public void setMediaGridView(MediaGridView mediaGridView) { /** * 分页获取media - * @param bucketId - * @param pageSize - * @param currentOffset */ @Override - public void getMediaList(String bucketId, int pageSize, int currentOffset) { - mediaSrcFactoryInteractor.generateMeidas(bucketId, pageSize, currentOffset); + public void getMediaList(String bucketId, int pageSize, int currentOffset,boolean isImage) { + mediaSrcFactoryInteractor.generateMeidas(bucketId, pageSize, currentOffset,isImage); } @Override @@ -60,9 +54,6 @@ public void getBucketList() { /** * Media获取事件回调 - * @param pageSize - * @param currentOffset - * @param list */ @Override public void onFinished(String bucketId, int pageSize, int currentOffset, List list) { @@ -71,7 +62,6 @@ public void onFinished(String bucketId, int pageSize, int currentOffset, List list) { 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/BaseResultEvent.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/BaseResultEvent.java index 16fb1af2..ae5c16b0 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/BaseResultEvent.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/BaseResultEvent.java @@ -2,7 +2,7 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/7/31 下午10:37 */ public interface BaseResultEvent { diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/CloseMediaViewPageFragmentEvent.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/CloseMediaViewPageFragmentEvent.java index 57ace29a..3187e836 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/CloseMediaViewPageFragmentEvent.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/CloseMediaViewPageFragmentEvent.java @@ -2,7 +2,7 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/7/28 上午12:19 */ public class CloseMediaViewPageFragmentEvent { diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/CloseRxMediaGridPageEvent.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/CloseRxMediaGridPageEvent.java index b0f269b6..ff2c5541 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/CloseRxMediaGridPageEvent.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/CloseRxMediaGridPageEvent.java @@ -2,7 +2,7 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/8/1 下午11:51 */ public class CloseRxMediaGridPageEvent { diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/ImageMultipleResultEvent.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/ImageMultipleResultEvent.java index 4ae493e3..68fd7653 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/ImageMultipleResultEvent.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/ImageMultipleResultEvent.java @@ -6,17 +6,17 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/8/1 下午10:52 */ public class ImageMultipleResultEvent implements BaseResultEvent { - private List mediaResultList; + private final List mediaResultList; public ImageMultipleResultEvent(List list) { this.mediaResultList = list; } - public List getResult(){ + public List getResult() { return mediaResultList; } } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/ImageRadioResultEvent.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/ImageRadioResultEvent.java index 39b1c37a..27ba44c2 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/ImageRadioResultEvent.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/ImageRadioResultEvent.java @@ -4,17 +4,18 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/8/1 下午10:49 */ public class ImageRadioResultEvent implements BaseResultEvent { - private ImageCropBean resultBean; + private final ImageCropBean resultBean; - public ImageRadioResultEvent(ImageCropBean bean){ + public ImageRadioResultEvent(ImageCropBean bean) { this.resultBean = bean; } public ImageCropBean getResult() { return resultBean; } + } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/MediaCheckChangeEvent.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/MediaCheckChangeEvent.java index c047e596..39d489f8 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/MediaCheckChangeEvent.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/MediaCheckChangeEvent.java @@ -4,14 +4,14 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/7/24 下午11:47 */ public class MediaCheckChangeEvent { - private MediaBean mediaBean; + private final MediaBean mediaBean; - public MediaCheckChangeEvent(MediaBean mediaBean){ + public MediaCheckChangeEvent(MediaBean mediaBean) { this.mediaBean = mediaBean; } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/MediaViewPagerChangedEvent.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/MediaViewPagerChangedEvent.java index 94a5106a..6eba01c5 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/MediaViewPagerChangedEvent.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/MediaViewPagerChangedEvent.java @@ -2,14 +2,14 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/7/25 下午3:45 */ public class MediaViewPagerChangedEvent { - private int curIndex; - private int totalSize; - private boolean isPreview; + private final int curIndex; + private final int totalSize; + private final boolean isPreview; public MediaViewPagerChangedEvent(int curIndex, int totalSize, boolean isPreview) { this.curIndex = curIndex; diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/OpenMediaPageFragmentEvent.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/OpenMediaPageFragmentEvent.java index 7878ec54..6e09e770 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/OpenMediaPageFragmentEvent.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/OpenMediaPageFragmentEvent.java @@ -6,14 +6,14 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/7/27 下午11:14 */ public class OpenMediaPageFragmentEvent { - private ArrayList mediaBeanList; - private int position; + private final ArrayList mediaBeanList; + private final int position; - public OpenMediaPageFragmentEvent(ArrayList mediaBeanList, int position){ + public OpenMediaPageFragmentEvent(ArrayList mediaBeanList, int position) { this.mediaBeanList = mediaBeanList; this.position = position; } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/OpenMediaPreviewFragmentEvent.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/OpenMediaPreviewFragmentEvent.java index e29488b9..7f7ecf4f 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/OpenMediaPreviewFragmentEvent.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxbus/event/OpenMediaPreviewFragmentEvent.java @@ -2,7 +2,7 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/7/23 下午3:49 */ public class OpenMediaPreviewFragmentEvent { 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..9ff8bbe5 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/rxjob/Job.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/rxjob/Job.java @@ -1,34 +1,36 @@ package cn.finalteam.rxgalleryfinal.rxjob; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; /** * 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/BaseActivity.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/activity/BaseActivity.java index d2bb3b05..ffd3525b 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 @@ -2,25 +2,26 @@ import android.content.Intent; import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.support.annotation.LayoutRes; -import android.support.annotation.Nullable; -import android.support.v7.app.AppCompatActivity; +import androidx.annotation.LayoutRes; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; import cn.finalteam.rxgalleryfinal.BuildConfig; import cn.finalteam.rxgalleryfinal.Configuration; +import cn.finalteam.rxgalleryfinal.R; import cn.finalteam.rxgalleryfinal.utils.Logger; +import cn.finalteam.rxgalleryfinal.utils.PermissionCheckUtils; +import cn.finalteam.rxgalleryfinal.utils.ThemeUtils; /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/5/16 下午7:36 */ public abstract class BaseActivity extends AppCompatActivity { public static final String EXTRA_PREFIX = BuildConfig.APPLICATION_ID; - public static final String EXTRA_CONFIGURATION = EXTRA_PREFIX +".Configuration"; + public static final String EXTRA_CONFIGURATION = EXTRA_PREFIX + ".Configuration"; private final String CLASS_NAME = getClass().getSimpleName(); @@ -32,22 +33,31 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { printActivityLife("onCreate"); Intent intent = getIntent(); Bundle bundle = null; - if(intent != null){ + if (intent != null) { bundle = intent.getExtras(); } - if(savedInstanceState != null){ + if (savedInstanceState != null) { mConfiguration = savedInstanceState.getParcelable(EXTRA_CONFIGURATION); } - if(mConfiguration == null && bundle != null) { + if (mConfiguration == null && bundle != null) { mConfiguration = bundle.getParcelable(EXTRA_CONFIGURATION); } - if(mConfiguration == null){ - mFinishHanlder.sendEmptyMessage(0); + //申请权限 +/* String requestStorageAccessPermissionTips = ThemeUtils.resolveString(this, + R.attr.gallery_request_storage_access_permission_tips, + R.string.gallery_default_request_storage_access_permission_tips); + if (PermissionCheckUtils.checkWriteExternalPermission(this, requestStorageAccessPermissionTips, MediaActivity.REQUEST_STORAGE_WRITE_ACCESS_PERMISSION) + && PermissionCheckUtils.checkReadExternalPermission(this, requestStorageAccessPermissionTips, MediaActivity.REQUEST_STORAGE_READ_ACCESS_PERMISSION)) { + + }*/ + + if (mConfiguration == null) { + finish(); } else { - if(bundle == null){ + if (bundle == null) { bundle = savedInstanceState; } setContentView(getContentView()); @@ -55,6 +65,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { setTheme(); onCreateOk(bundle); } + } @LayoutRes @@ -108,17 +119,9 @@ protected void onRestoreInstanceState(Bundle savedInstanceState) { public abstract void findViews(); - protected Handler mFinishHanlder = new Handler() { - @Override - public void handleMessage(Message msg) { - super.handleMessage(msg); - finish(); - } - }; - protected abstract void setTheme(); - private void printActivityLife(String method){ + private void printActivityLife(String method) { Logger.i(String.format("Activity:%s Method:%s", CLASS_NAME, method)); } } 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..1c44c1ff 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 @@ -7,10 +7,10 @@ import android.graphics.drawable.StateListDrawable; import android.graphics.drawable.shapes.RoundRectShape; import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.FragmentTransaction; -import android.support.v7.widget.Toolbar; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.FragmentTransaction; +import androidx.appcompat.widget.Toolbar; import android.util.TypedValue; import android.view.KeyEvent; import android.view.MenuItem; @@ -24,15 +24,16 @@ 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.ImageRadioResultEvent; 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 +42,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 +61,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 +84,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 +102,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 +135,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 +180,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 +195,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 +203,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,16 +231,18 @@ 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.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); @@ -263,9 +280,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; @@ -275,19 +292,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); @@ -299,14 +316,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; @@ -317,8 +334,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(); @@ -326,8 +343,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(); @@ -344,17 +361,31 @@ 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; } + //cancel return [] + if(!mConfiguration.isMultiple()){ + BaseResultEvent event = new ImageRadioResultEvent(null); + RxBus.getDefault().post(event); + }else{ + BaseResultEvent event = new ImageMultipleResultEvent(new ArrayList<>()); + RxBus.getDefault().post(event); + } + + onBackPressed(); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { - if(keyCode == KeyEvent.KEYCODE_BACK){ + if (keyCode == KeyEvent.KEYCODE_BACK) { backAction(); return true; } @@ -373,7 +404,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); @@ -394,18 +425,35 @@ 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]); - switch (requestCode) { - case REQUEST_STORAGE_READ_ACCESS_PERMISSION: - if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { - RxBus.getDefault().post(new RequestStorageReadAccessPermissionEvent(true)); - } else { - finish(); - } - break; - default: - super.onRequestPermissionsResult(requestCode, permissions, grantResults); + Logger.i("onRequestPermissionsResult:requestCode=" + requestCode + " permissions=" + permissions); + if(grantResults.length>0){ + switch (requestCode) { + case REQUEST_STORAGE_READ_ACCESS_PERMISSION: + if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { + 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); + } + }else{ + finish(); } } + } 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..c0f1e3c8 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 @@ -5,9 +5,10 @@ import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; -import android.support.v4.widget.CompoundButtonCompat; -import android.support.v7.widget.AppCompatRadioButton; -import android.support.v7.widget.RecyclerView; +import androidx.annotation.ColorInt; +import androidx.core.widget.CompoundButtonCompat; +import androidx.appcompat.widget.AppCompatRadioButton; +import androidx.recyclerview.widget.RecyclerView; import android.text.SpannableString; import android.text.Spanned; import android.text.TextUtils; @@ -29,60 +30,65 @@ /** * 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 final List mBucketList; + private final Drawable mDefaultImage; private Context mContext; - private LayoutInflater mInflater; - private Drawable mDefaultImage; - private Configuration mConfiguration; + private final Configuration mConfiguration; private OnRecyclerViewItemClickListener mOnRecyclerViewItemClickListener; private BucketBean mSelectedBucket; - public BucketAdapter(Context context, List bucketList, Configuration configuration) { - this.mContext = context; + public BucketAdapter( + Context mContex, + List bucketList, + Configuration configuration, + @ColorInt int color) { + this.mContext = mContex; 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() + "张"); - 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())) { - holder.mRbSelected.setVisibility(View.VISIBLE); - holder.mRbSelected.setChecked(true); - } else { - holder.mRbSelected.setVisibility(View.GONE); - } + if(bucketName!=null){ + if (position != 0) { + 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); + } else { + holder.mTvBucketName.setText(bucketName); + } + if (mSelectedBucket != null && TextUtils.equals(mSelectedBucket.getBucketId(), bucketBean.getBucketId())) { + holder.mRbSelected.setVisibility(View.VISIBLE); + holder.mRbSelected.setChecked(true); + } else { + holder.mRbSelected.setVisibility(View.GONE); + } - String path = bucketBean.getCover(); - mConfiguration.getImageLoader() - .displayImage(mContext, path, holder.mIvBucketCover, mDefaultImage, mConfiguration.getImageConfig(), - true, 100, 100, bucketBean.getOrientation()); + String path = bucketBean.getCover(); + mConfiguration.getImageLoader() + .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 +100,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 +121,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 +138,6 @@ public void onClick(View v) { /** * 设置未所有Item为未选中 - * @param parentView */ private void setRadioDisChecked(ViewGroup parentView) { if (parentView == null || parentView.getChildCount() < 1) { @@ -138,15 +147,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..d4b84708 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,19 +1,21 @@ package cn.finalteam.rxgalleryfinal.ui.adapter; -import android.content.Context; import android.content.res.ColorStateList; import android.graphics.drawable.Drawable; -import android.support.v4.widget.CompoundButtonCompat; -import android.support.v7.widget.AppCompatCheckBox; -import android.support.v7.widget.RecyclerView; +import androidx.core.content.ContextCompat; +import androidx.core.widget.CompoundButtonCompat; +import androidx.appcompat.widget.AppCompatCheckBox; +import androidx.recyclerview.widget.RecyclerView; import android.text.TextUtils; 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,126 @@ 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 / configuration.getSpanCount(); 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.gallery_item_media_grid, parent, false); + } else { + view = LayoutInflater.from(parent.getContext()).inflate(R.layout.gallery_item_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) { - holder.mCbCheck.setVisibility(View.GONE); - holder.mIvMediaImage.setVisibility(View.GONE); - holder.mLlCamera.setVisibility(View.VISIBLE); - holder.mIvCameraImage.setImageDrawable(mCameraImage); - holder.mTvCameraTxt.setTextColor(mCameraTextColor); - } else { - if(mConfiguration.isRadio()) { + if(mediaBean!=null){ + if (mediaBean.getId() == Integer.MIN_VALUE) { holder.mCbCheck.setVisibility(View.GONE); - } else{ - holder.mCbCheck.setVisibility(View.VISIBLE); - holder.mCbCheck.setOnClickListener(new OnCheckBoxClickListener(mediaBean)); - } - holder.mIvMediaImage.setVisibility(View.VISIBLE); - holder.mLlCamera.setVisibility(View.GONE); - if(mMediaActivity.getCheckedList() != null && mMediaActivity.getCheckedList().contains(mediaBean)){ - holder.mCbCheck.setChecked(true); + 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 { - holder.mCbCheck.setChecked(false); + if (mConfiguration.isRadio()) { + holder.mCbCheck.setVisibility(View.GONE); + } 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); + 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()) { + Job job = new ImageThmbnailJobCreate(mMediaActivity, mediaBean).create(); + RxJob.getDefault().addJob(job); + } + 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()); + } } - String bitPath = mediaBean.getThumbnailSmallPath(); - String smallPath = mediaBean.getThumbnailSmallPath(); - - 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)) { - path = mediaBean.getOriginalPath(); - } - - OsCompat.setBackgroundDrawableCompat(holder.mIvMediaImage, mImageViewBg); - - mConfiguration.getImageLoader() - .displayImage(mMediaActivity, path, holder.mIvMediaImage, mDefaultImage, mConfiguration.getImageConfig(), - true, mImageSize, mImageSize, mediaBean.getOrientation()); } } @@ -121,49 +151,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; + + + 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; - public OnCheckBoxClickListener(MediaBean bean) { + 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/adapter/RecyclingPagerAdapter.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/adapter/RecyclingPagerAdapter.java index 28d9966a..68fc685d 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/adapter/RecyclingPagerAdapter.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/adapter/RecyclingPagerAdapter.java @@ -1,7 +1,7 @@ package cn.finalteam.rxgalleryfinal.ui.adapter; import android.os.Build; -import android.support.v4.view.PagerAdapter; +import androidx.viewpager.widget.PagerAdapter; import android.util.SparseArray; import android.view.View; import android.view.ViewGroup; @@ -11,19 +11,19 @@ * Desction: * A {@link PagerAdapter} which behaves like an {@link android.widget.Adapter} with view types and * view recycling. - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:15/12/22 下午6:21 */ -public abstract class RecyclingPagerAdapter extends PagerAdapter { - static final int IGNORE_ITEM_VIEW_TYPE = AdapterView.ITEM_VIEW_TYPE_IGNORE; +abstract class RecyclingPagerAdapter extends PagerAdapter { + private static final int IGNORE_ITEM_VIEW_TYPE = AdapterView.ITEM_VIEW_TYPE_IGNORE; private final RecycleBin recycleBin; - public RecyclingPagerAdapter() { + RecyclingPagerAdapter() { this(new RecycleBin()); } - RecyclingPagerAdapter(RecycleBin recycleBin) { + private RecyclingPagerAdapter(RecycleBin recycleBin) { this.recycleBin = recycleBin; recycleBin.setViewTypeCount(getViewTypeCount()); } @@ -75,7 +75,7 @@ public final boolean isViewFromObject(View view, Object object) { * * @return The number of types of Views that will be created by this adapter */ - public int getViewTypeCount() { + private int getViewTypeCount() { return 1; } @@ -83,7 +83,7 @@ public int getViewTypeCount() { * Get the type of View that will be created by {@link #getView} for the specified item. * * @param position The position of the item within the adapter's data set whose view type we - * want. + * want. * @return An integer representing the type of View. Two views should share the same type if one * can be converted to the other in {@link #getView}. Note: Integers must be in the * range 0 to {@link #getViewTypeCount} - 1. {@link #IGNORE_ITEM_VIEW_TYPE} can @@ -91,7 +91,7 @@ public int getViewTypeCount() { * @see #IGNORE_ITEM_VIEW_TYPE */ @SuppressWarnings("UnusedParameters") // Argument potentially used by subclasses. - public int getItemViewType(int position) { + private int getItemViewType(int position) { return 0; } @@ -102,18 +102,18 @@ public int getItemViewType(int position) { * {@link android.view.LayoutInflater#inflate(int, ViewGroup, boolean)} * to specify a root view and to prevent attachment to the root. * - * @param position The position of the item within the adapter's data set of the item whose view - * we want. + * @param position The position of the item within the adapter's data set of the item whose view + * we want. * @param convertView The old view to reuse, if possible. Note: You should check that this view - * is non-null and of an appropriate type before using. If it is not possible to convert - * this view to display the correct data, this method can create a new view. - * Heterogeneous lists can specify their number of view types, so that this View is - * always of the right type (see {@link #getViewTypeCount()} and - * {@link #getItemViewType(int)}). - * @param container The parent that this view will eventually be attached to + * is non-null and of an appropriate type before using. If it is not possible to convert + * this view to display the correct data, this method can create a new view. + * Heterogeneous lists can specify their number of view types, so that this View is + * always of the right type (see {@link #getViewTypeCount()} and + * {@link #getItemViewType(int)}). + * @param container The parent that this view will eventually be attached to * @return A View corresponding to the data at the specified position. */ - public abstract View getView(int position, View convertView, ViewGroup container); + protected abstract View getView(int position, View convertView, ViewGroup container); /** * The RecycleBin facilitates reuse of views across layouts. The RecycleBin has two levels of @@ -132,16 +132,39 @@ public static class RecycleBin { * Views in activeViews represent a contiguous range of Views, with position of the first * view store in mFirstActivePosition. */ - private View[] activeViews = new View[0]; - private int[] activeViewTypes = new int[0]; + private final View[] activeViews = new View[0]; + private final int[] activeViewTypes = new int[0]; - /** Unsorted views that can be used by the adapter as a convert view. */ + /** + * Unsorted views that can be used by the adapter as a convert view. + */ private SparseArray[] scrapViews; private int viewTypeCount; private SparseArray currentScrapViews; + static View retrieveFromScrap(SparseArray scrapViews, int position) { + int size = scrapViews.size(); + if (size > 0) { + // See if we still have a view for this position. + for (int i = 0; i < size; i++) { + int fromPosition = scrapViews.keyAt(i); + View view = scrapViews.get(fromPosition); + if (fromPosition == position) { + scrapViews.remove(fromPosition); + return view; + } + } + int index = size - 1; + View r = scrapViews.valueAt(index); + scrapViews.remove(scrapViews.keyAt(index)); + return r; + } else { + return null; + } + } + public void setViewTypeCount(int viewTypeCount) { if (viewTypeCount < 1) { throw new IllegalArgumentException("Can't have a viewTypeCount < 1"); @@ -149,18 +172,20 @@ public void setViewTypeCount(int viewTypeCount) { //noinspection unchecked SparseArray[] scrapViews = new SparseArray[viewTypeCount]; for (int i = 0; i < viewTypeCount; i++) { - scrapViews[i] = new SparseArray(); + scrapViews[i] = new SparseArray<>(); } this.viewTypeCount = viewTypeCount; currentScrapViews = scrapViews[0]; this.scrapViews = scrapViews; } - protected boolean shouldRecycleViewType(int viewType) { + boolean shouldRecycleViewType(int viewType) { return viewType >= 0; } - /** @return A view from the ScrapViews collection. These are unordered. */ + /** + * @return A view from the ScrapViews collection. These are unordered. + */ View getScrapView(int position, int viewType) { if (viewTypeCount == 1) { return retrieveFromScrap(currentScrapViews, position); @@ -187,7 +212,9 @@ void addScrapView(View scrap, int position, int viewType) { } } - /** Move all views remaining in activeViews to scrapViews. */ + /** + * Move all views remaining in activeViews to scrapViews. + */ void scrapActiveViews() { final View[] activeViews = this.activeViews; final int[] activeViewTypes = this.activeViewTypes; @@ -239,26 +266,5 @@ private void pruneScrapViews() { } } } - - static View retrieveFromScrap(SparseArray scrapViews, int position) { - int size = scrapViews.size(); - if (size > 0) { - // See if we still have a view for this position. - for (int i = 0; i < size; i++) { - int fromPosition = scrapViews.keyAt(i); - View view = scrapViews.get(fromPosition); - if (fromPosition == position) { - scrapViews.remove(fromPosition); - return view; - } - } - int index = size - 1; - View r = scrapViews.valueAt(index); - scrapViews.remove(scrapViews.keyAt(index)); - return r; - } else { - return null; - } - } } } 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/BaseFragment.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/BaseFragment.java index 4028e64b..b48d75f2 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/BaseFragment.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/BaseFragment.java @@ -1,31 +1,34 @@ package cn.finalteam.rxgalleryfinal.ui.fragment; import android.content.Context; +import android.content.Intent; import android.os.Bundle; -import android.support.annotation.Nullable; -import android.support.v4.app.Fragment; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import java.util.Stack; + import cn.finalteam.rxgalleryfinal.BuildConfig; import cn.finalteam.rxgalleryfinal.Configuration; import cn.finalteam.rxgalleryfinal.utils.Logger; /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/5/14 上午10:46 */ public abstract class BaseFragment extends Fragment { - private final String CLASS_NAME = getClass().getSimpleName(); public static final String EXTRA_PREFIX = BuildConfig.APPLICATION_ID; - public static final String EXTRA_CONFIGURATION = EXTRA_PREFIX +".Configuration"; - + public static final String EXTRA_CONFIGURATION = EXTRA_PREFIX + ".Configuration"; + private static Stack fragmentStack = new Stack<>(); + private final String CLASS_NAME = getClass().getSimpleName(); protected Bundle mSaveDataBundle; protected String BUNDLE_KEY = "KEY_" + CLASS_NAME; - protected Configuration mConfiguration; @Override @@ -47,29 +50,29 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { Bundle argsBundle = getArguments(); - if(savedInstanceState != null){ + if (savedInstanceState != null) { mConfiguration = savedInstanceState.getParcelable(EXTRA_CONFIGURATION); } - if(mConfiguration == null && argsBundle != null) { + if (mConfiguration == null && argsBundle != null) { mConfiguration = argsBundle.getParcelable(EXTRA_CONFIGURATION); } - if(mConfiguration != null){ - if(argsBundle == null){ + if (mConfiguration != null) { + if (argsBundle == null) { argsBundle = savedInstanceState; } onViewCreatedOk(view, argsBundle); setTheme(); } else { - if(getActivity() != null && !getActivity().isFinishing()) { - getActivity().finish(); + FragmentActivity activity = getActivity(); + if (activity != null && !activity.isFinishing()) { + activity.finish(); } } } public abstract void onViewCreatedOk(View view, @Nullable Bundle savedInstanceState); - @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { @@ -77,6 +80,30 @@ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, return inflater.inflate(getContentView(), container, false); } + @Override + public void startActivityForResult(Intent intent, int requestCode) { + Logger.i("startActivityForResult"); + Fragment parentFragment = getParentFragment(); + if (null != parentFragment) { + fragmentStack.push(this); + parentFragment.startActivityForResult(intent, requestCode); + } else { + super.startActivityForResult(intent, requestCode); + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + Logger.i("onActivityResult"); + BaseFragment fragment = fragmentStack.isEmpty() ? null : fragmentStack.pop(); + if (null != fragment) { + fragment.onActivityResult(requestCode, resultCode, data); + return; + } + super.onActivityResult(requestCode, resultCode, data); + } + + @Override public void onStart() { super.onStart(); @@ -116,9 +143,10 @@ public void onDetach() { public abstract int getContentView(); - public void setTheme(){} + public void setTheme() { + } - private void printFragmentLife(String method){ + private void printFragmentLife(String method) { Logger.i(String.format("Fragment:%s Method:%s", CLASS_NAME, method)); } @@ -147,7 +175,7 @@ private void saveStateToArguments() { if (mSaveDataBundle != null) { Bundle b = getArguments(); - if(b != null) { + if (b != null) { b.putBundle(BUNDLE_KEY, mSaveDataBundle); } } @@ -155,7 +183,7 @@ private void saveStateToArguments() { private boolean restoreStateFromArguments() { Bundle b = getArguments(); - if(b != null) { + if (b != null) { mSaveDataBundle = b.getBundle(BUNDLE_KEY); if (mSaveDataBundle != null) { restoreState(); @@ -177,7 +205,6 @@ private void restoreState() { /** * 恢复数据 - * @param savedInstanceState */ protected abstract void onRestoreState(Bundle savedInstanceState); 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..90719709 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 @@ -4,13 +4,10 @@ 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.v7.widget.GridLayoutManager; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; import android.text.TextUtils; import android.util.DisplayMetrics; import android.view.View; @@ -19,7 +16,18 @@ import android.widget.TextView; import android.widget.Toast; +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.FragmentActivity; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.hjq.permissions.OnPermissionCallback; +import com.yalantis.ucrop.UCrop; import com.yalantis.ucrop.UCropActivity; +import com.yalantis.ucrop.model.AspectRatio; +import com.zhy.base.fileprovider.FileProvider7; import java.io.File; import java.text.SimpleDateFormat; @@ -27,6 +35,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; @@ -38,16 +47,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.RxBusDisposable; import cn.finalteam.rxgalleryfinal.rxbus.event.CloseMediaViewPageFragmentEvent; 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; @@ -55,36 +65,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; @@ -96,20 +120,31 @@ 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 File mImageStoreCropDir; private String mImagePath; private String mBucketId = String.valueOf(Integer.MIN_VALUE); private MediaActivity mMediaActivity; - private Subscription mSubscrMediaCheckChangeEvent; - private Subscription mSubscrCloseMediaViewPageFragmentEvent; - private Subscription mSubscrRequestStorageReadAccessPermissionEvent; + 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; + + private boolean currShowType ; + + private static String rootPath = "myrxgalleryfinal"; public static MediaGridFragment newInstance(Configuration configuration) { MediaGridFragment fragment = new MediaGridFragment(); @@ -119,17 +154,28 @@ public static MediaGridFragment newInstance(Configuration configuration) { return fragment; } + public static void setRadioListener(IRadioImageCheckedListener radioListener) { + MediaGridFragment.iListenerRadio = radioListener; + } + + public static String getImageStoreDirByStr() { + if (mImageStoreDir != null) + return mImageStoreDir.getPath(); + else{ + mImageStoreDir = new File(Environment.getExternalStorageDirectory(), rootPath); + if (!mImageStoreDir.exists()) { + mImageStoreDir.mkdirs(); + } + } + return mImageStoreDir.getPath(); + } + @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/"); - mImageStoreCropDir = new File(mImageStoreDir, "crop"); - if (!mImageStoreCropDir.exists()) { - mImageStoreCropDir.mkdirs(); - } mMediaScanner = new MediaScanner(context); } @@ -140,6 +186,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); @@ -147,7 +194,7 @@ public void onViewCreatedOk(View view, @Nullable Bundle savedInstanceState) { mRlRootView = (RelativeLayout) view.findViewById(R.id.rl_root_view); mRvMedia.setEmptyView(mLlEmptyView); - GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), 3); + GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), mConfiguration.getSpanCount()); gridLayoutManager.setOrientation(GridLayoutManager.VERTICAL); mRvMedia.addItemDecoration(new MarginDecoration(getContext())); mRvMedia.setLayoutManager(gridLayoutManager); @@ -159,15 +206,24 @@ 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()){ + currShowType = mConfiguration.isImage(); + 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); @@ -182,40 +238,63 @@ public void onViewCreatedOk(View view, @Nullable Bundle savedInstanceState) { .build()); mRvBucket.setLayoutManager(linearLayoutManager); mBucketBeanList = new ArrayList<>(); - mBucketAdapter = new BucketAdapter(getContext(), mBucketBeanList, mConfiguration); + mBucketAdapter = new BucketAdapter(getContext(),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) { - mMediaGridPresenter.getMediaList(mBucketId, mPage, LIMIT); - } + PermissionCheckUtils.checkWriteExternalPermission(activity, requestStorageAccessPermissionTips, + MediaActivity.REQUEST_STORAGE_WRITE_ACCESS_PERMISSION,new OnPermissionCallback() { + + @Override + public void onGranted(List permissions, boolean all) { + mMediaGridPresenter.getMediaList(mBucketId, mPage, LIMIT,currShowType); + } + + @Override + public void onDenied(List permissions, boolean never) { + + } + }); + } + /** + * 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); @@ -223,53 +302,90 @@ 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,currShowType); + } 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(mConfiguration.isOpenCameraOnStart()){ + onLoadFile(); + this.openCameraOnStart(); + } + } + + public void openCameraOnStart(){ + if (!CameraUtils.hasCamera(getContext())) { + Toast.makeText(getContext(), R.string.gallery_device_no_camera_tips, Toast.LENGTH_SHORT).show(); + return; + } + openCamera(mMediaActivity); + } + + @Override + public void onStart() { + super.onStart(); + onLoadFile(); + //直接刷新一次 + // refreshUI(); } + @Override public void loadMore() { - mMediaGridPresenter.getMediaList(mBucketId, mPage, LIMIT); + mMediaGridPresenter.getMediaList(mBucketId, mPage, LIMIT,currShowType); } @Override public void onRequestMediaCallback(List list) { - if(!mConfiguration.isHideCamera()) { - if (mPage == 1 && TextUtils.equals(mBucketId, String.valueOf(Integer.MIN_VALUE))) { + if (!mConfiguration.isHideCamera()) { + if (mPage == 1 && TextUtils.equals(mBucketId, String.valueOf(Integer.MIN_VALUE)) + && mMediaBeanList.size()==0) { MediaBean takePhotoBean = new MediaBean(); takePhotoBean.setId(Integer.MIN_VALUE); takePhotoBean.setBucketId(String.valueOf(Integer.MIN_VALUE)); @@ -277,7 +393,18 @@ public void onRequestMediaCallback(List list) { } } if (list != null && list.size() > 0) { - mMediaBeanList.addAll(list); + //说明原来有图片,说明是从相机返回,增量添加 + if(mMediaBeanList.size()>1 && mPage==1 && currShowType== mConfiguration.isImage()){ + list.removeAll(mMediaBeanList); + if(list!=null && list.size()>0){ + mMediaBeanList.addAll(1,list); + checkMediaBean(list); + mMediaGridAdapter.notifyDataSetChanged(); + } + return; + }else { + mMediaBeanList.addAll(list); + } Logger.i(String.format("得到:%s张图片", list.size())); } else { Logger.i("没有更多图片"); @@ -286,9 +413,19 @@ public void onRequestMediaCallback(List list) { mPage++; - if (list == null || list.size() < LIMIT) { - mRvMedia.setFooterViewHide(true); - mRvMedia.setHasLoadMore(false); + if (list == null || list.size()==0 || list.size() <= (LIMIT-3)) { + if(currShowType== mConfiguration.isImage() && mConfiguration.isSelectBoth() + && TextUtils.equals(mBucketId, String.valueOf(Integer.MIN_VALUE)) + ){ + mPage = 1; + currShowType = !currShowType; + mRvMedia.setFooterViewHide(false); + mRvMedia.setHasLoadMore(true); + this.loadMore(); + }else { + mRvMedia.setFooterViewHide(true); + mRvMedia.setHasLoadMore(false); + } } else { mRvMedia.setFooterViewHide(false); mRvMedia.setHasLoadMore(true); @@ -304,13 +441,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 @@ -318,7 +454,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; @@ -326,15 +462,20 @@ 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); + currShowType = mConfiguration.isImage(); + mMediaGridPresenter.getMediaList(mBucketId, mPage, LIMIT,currShowType); } @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) { @@ -343,17 +484,20 @@ public void onItemClick(RecyclerView.ViewHolder holder, int position) { return; } - openCamera(); - + 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()); @@ -364,37 +508,163 @@ 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(mImageStoreCropDir, 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); + + FileProvider7.grantPermissions(getActivity(),intent,outUri,true); + + // UCrop 参数 start 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.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_CONTROLS_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()); + 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()); + 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) { + FragmentActivity activity = this.getActivity(); + PermissionCheckUtils.checkCameraPermission(mMediaActivity, requestStorageAccessPermissionTips, MediaActivity.REQUEST_CAMERA_ACCESS_PERMISSION,new OnPermissionCallback() { + + @Override + public void onGranted(List permissions, boolean all) { + + boolean image = mConfiguration.isImage(); + + 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; + } + if(mConfiguration.isMultipleShot() && image){ + captureIntent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); + } + + 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(); + + Uri pictureUri = null; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + //""中的内容是随意的,但最好用package名.provider名的形式,清晰明了 + pictureUri = FileProvider7.getUriForFile(activity, fileImagePath); + } else { + pictureUri = Uri.fromFile(fileImagePath); + } + + captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, pictureUri); + // video : 1: 高质量 0 低质量 + if(!image){ + captureIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, mConfiguration.getVideoQuality()); + } + //这一句非常重要 + captureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + captureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + + startActivityForResult(captureIntent, TAKE_IMAGE_REQUEST_CODE); + } + + @Override + public void onDenied(List permissions, boolean never) { + + } + }); + } @Override @@ -403,9 +673,47 @@ 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 == TAKE_IMAGE_REQUEST_CODE && resultCode == Activity.RESULT_CANCELED) { + if(mConfiguration.isReturnAfterShot()){ + getActivity().finish(); + } + } else if (requestCode == 222) { + Toast.makeText(getActivity(), "摄像成功", Toast.LENGTH_SHORT).show(); + } else if (requestCode == CROP_IMAGE_REQUEST_CODE && data != null) { + Logger.i("裁剪成功"); + onCropFinished(); + } + //重新加载图片 + mPage = 1; + currShowType = mConfiguration.isImage(); + mMediaGridPresenter.getMediaList(mBucketId, mPage, LIMIT,currShowType); + } - //刷新相册数据库 - 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(); } } @@ -415,7 +723,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); } } @@ -425,6 +733,9 @@ protected void onRestoreState(Bundle savedInstanceState) { } + + //**************************************************************************** + @Override protected void onSaveState(Bundle outState) { @@ -449,73 +760,139 @@ 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(); + } + @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) { + @Override + public void onError(Throwable e) { + Logger.i("获取MediaBean异常" + e.toString()); + } - if(!isDetached() && mediaBean != null) { - mMediaBeanList.add(1, mediaBean); - mMediaGridAdapter.notifyDataSetChanged(); - } + @Override + public void onNext(MediaBean mediaBean) { + if (!isDetached() && mediaBean != null) { + int bk = FileUtils.existImageDir(mediaBean.getOriginalPath()); + if (bk != -1) { + if(mConfiguration.isReturnAfterShot()){ + if (mConfiguration.isImage()) { + radioNext(mediaBean); + } else { + videoRadioNext(mediaBean); + } + }else{ + mMediaBeanList.add(1, mediaBean); + checkMediaBean(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 (mImageStoreDir == null) { + mImageStoreDir = new File(Environment.getExternalStorageDirectory(), rootPath); + } + if (!mImageStoreDir.exists()) { + mImageStoreDir.mkdirs(); + } + if (mImageStoreCropDir== null) { + mImageStoreCropDir = new File(mImageStoreDir, "crop"); + if (!mImageStoreCropDir.exists()) { + mImageStoreCropDir.mkdirs(); + } + } + } + + public void checkMediaBean(MediaBean mediaBean){ + if(!mConfiguration.isRadio() && mMediaActivity.getCheckedList().size() list){ + for (MediaBean mediaBean:list){ + checkMediaBean(mediaBean); + } } } 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..7cb6418d 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 @@ -3,10 +3,11 @@ import android.content.Context; import android.content.res.ColorStateList; import android.os.Bundle; -import android.support.annotation.Nullable; -import android.support.v4.view.ViewPager; -import android.support.v4.widget.CompoundButtonCompat; -import android.support.v7.widget.AppCompatCheckBox; +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; +import androidx.viewpager.widget.ViewPager; +import androidx.core.widget.CompoundButtonCompat; +import androidx.appcompat.widget.AppCompatCheckBox; import android.util.DisplayMetrics; import android.view.View; import android.widget.RelativeLayout; @@ -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..53db2916 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 @@ -3,10 +3,11 @@ import android.content.Context; import android.content.res.ColorStateList; import android.os.Bundle; -import android.support.annotation.Nullable; -import android.support.v4.view.ViewPager; -import android.support.v4.widget.CompoundButtonCompat; -import android.support.v7.widget.AppCompatCheckBox; +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; +import androidx.viewpager.widget.ViewPager; +import androidx.core.widget.CompoundButtonCompat; +import androidx.appcompat.widget.AppCompatCheckBox; import android.util.DisplayMetrics; import android.view.View; import android.widget.RelativeLayout; @@ -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/ui/widget/FixImageView.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FixImageView.java index 3baf38ac..9dfd5a8e 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FixImageView.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FixImageView.java @@ -3,13 +3,14 @@ import android.content.Context; import android.graphics.Canvas; import android.graphics.drawable.Drawable; -import android.support.v7.widget.AppCompatImageView; +import androidx.annotation.NonNull; +import androidx.appcompat.widget.AppCompatImageView; import android.util.AttributeSet; import android.view.MotionEvent; /** * Desction:为了兼容fresco框架而自定义的ImageView - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:2015/12/24 0024 20:14 */ public class FixImageView extends AppCompatImageView { @@ -32,18 +33,10 @@ public void setOnImageViewListener(OnImageViewListener listener) { mOnImageViewListener = listener; } - public static interface OnImageViewListener { - void onDetach(); - void onAttach(); - boolean verifyDrawable(Drawable dr) ; - void onDraw(Canvas canvas); - boolean onTouchEvent(MotionEvent event); - } - @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); - if(mOnImageViewListener != null) { + if (mOnImageViewListener != null) { mOnImageViewListener.onDetach(); } } @@ -51,14 +44,14 @@ protected void onDetachedFromWindow() { @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); - if(mOnImageViewListener != null) { + if (mOnImageViewListener != null) { mOnImageViewListener.onAttach(); } } @Override - protected boolean verifyDrawable(Drawable dr) { - if(mOnImageViewListener != null) { + protected boolean verifyDrawable(@NonNull Drawable dr) { + if (mOnImageViewListener != null) { if (mOnImageViewListener.verifyDrawable(dr)) { return true; } @@ -69,7 +62,7 @@ protected boolean verifyDrawable(Drawable dr) { @Override public void onStartTemporaryDetach() { super.onStartTemporaryDetach(); - if(mOnImageViewListener != null) { + if (mOnImageViewListener != null) { mOnImageViewListener.onDetach(); } } @@ -77,7 +70,7 @@ public void onStartTemporaryDetach() { @Override public void onFinishTemporaryDetach() { super.onFinishTemporaryDetach(); - if(mOnImageViewListener != null) { + if (mOnImageViewListener != null) { mOnImageViewListener.onAttach(); } } @@ -85,7 +78,7 @@ public void onFinishTemporaryDetach() { @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); - if(mOnImageViewListener != null) { + if (mOnImageViewListener != null) { mOnImageViewListener.onDraw(canvas); } @@ -93,10 +86,22 @@ protected void onDraw(Canvas canvas) { @Override public boolean onTouchEvent(MotionEvent event) { - if(mOnImageViewListener == null){ + if (mOnImageViewListener == null) { return super.onTouchEvent(event); } return mOnImageViewListener.onTouchEvent(event) || super.onTouchEvent(event); } + public interface OnImageViewListener { + void onDetach(); + + void onAttach(); + + boolean verifyDrawable(Drawable dr); + + void onDraw(Canvas canvas); + + boolean onTouchEvent(MotionEvent event); + } + } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FixViewPager.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FixViewPager.java index f8e59897..087f9286 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FixViewPager.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FixViewPager.java @@ -1,16 +1,16 @@ package cn.finalteam.rxgalleryfinal.ui.widget; import android.content.Context; -import android.support.v4.view.ViewPager; +import androidx.viewpager.widget.ViewPager; import android.util.AttributeSet; import android.view.MotionEvent; /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:2015/12/29 0029 19:29 */ -public class FixViewPager extends ViewPager{ +public class FixViewPager extends ViewPager { public FixViewPager(Context context) { super(context); } @@ -22,11 +22,9 @@ public FixViewPager(Context context, AttributeSet attrs) { @Override public boolean dispatchTouchEvent(MotionEvent ev) { try { - return super .dispatchTouchEvent(ev); + return super.dispatchTouchEvent(ev); } catch (IllegalArgumentException ignored) { - } catch (ArrayIndexOutOfBoundsException e) { } - - return false ; + return false; } } \ No newline at end of file diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FlexibleDividerDecoration.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FlexibleDividerDecoration.java index ef92909e..77d125dd 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FlexibleDividerDecoration.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FlexibleDividerDecoration.java @@ -7,17 +7,17 @@ import android.graphics.Paint; import android.graphics.Rect; import android.graphics.drawable.Drawable; -import android.support.annotation.ColorRes; -import android.support.annotation.DimenRes; -import android.support.annotation.DrawableRes; -import android.support.v4.content.ContextCompat; -import android.support.v7.widget.GridLayoutManager; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; +import androidx.annotation.ColorRes; +import androidx.annotation.DimenRes; +import androidx.annotation.DrawableRes; +import androidx.core.content.ContextCompat; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import android.view.View; /** - * Created by yqritc on 2015/01/08. + * by yqritc on 2015/01/08. */ public abstract class FlexibleDividerDecoration extends RecyclerView.ItemDecoration { @@ -25,22 +25,17 @@ public abstract class FlexibleDividerDecoration extends RecyclerView.ItemDecorat private static final int[] ATTRS = new int[]{ android.R.attr.listDivider }; - - protected enum DividerType { - DRAWABLE, PAINT, COLOR - } - - protected DividerType mDividerType = DividerType.DRAWABLE; - protected VisibilityProvider mVisibilityProvider; - protected PaintProvider mPaintProvider; - protected ColorProvider mColorProvider; - protected DrawableProvider mDrawableProvider; - protected SizeProvider mSizeProvider; - protected boolean mShowLastDivider; - protected boolean mPositionInsideItem; + final boolean mPositionInsideItem; + private final VisibilityProvider mVisibilityProvider; + private final boolean mShowLastDivider; + DividerType mDividerType = DividerType.DRAWABLE; + PaintProvider mPaintProvider; + DrawableProvider mDrawableProvider; + SizeProvider mSizeProvider; + private ColorProvider mColorProvider; private Paint mPaint; - protected FlexibleDividerDecoration(Builder builder) { + FlexibleDividerDecoration(Builder builder) { if (builder.mPaintProvider != null) { mDividerType = DividerType.PAINT; mPaintProvider = builder.mPaintProvider; @@ -55,12 +50,7 @@ protected FlexibleDividerDecoration(Builder builder) { TypedArray a = builder.mContext.obtainStyledAttributes(ATTRS); final Drawable divider = a.getDrawable(0); a.recycle(); - mDrawableProvider = new DrawableProvider() { - @Override - public Drawable drawableProvider(int position, RecyclerView parent) { - return divider; - } - }; + mDrawableProvider = (position, parent) -> divider; } else { mDrawableProvider = builder.mDrawableProvider; } @@ -75,12 +65,7 @@ public Drawable drawableProvider(int position, RecyclerView parent) { private void setSizeProvider(Builder builder) { mSizeProvider = builder.mSizeProvider; if (mSizeProvider == null) { - mSizeProvider = new SizeProvider() { - @Override - public int dividerSize(int position, RecyclerView parent) { - return DEFAULT_SIZE; - } - }; + mSizeProvider = (position, parent) -> DEFAULT_SIZE; } } @@ -164,13 +149,9 @@ public void getItemOffsets(Rect rect, View v, RecyclerView parent, RecyclerView. * @param parent RecyclerView * @return true if recyclerview is reverse layout */ - protected boolean isReverseLayout(RecyclerView parent) { + boolean isReverseLayout(RecyclerView parent) { RecyclerView.LayoutManager layoutManager = parent.getLayoutManager(); - if (layoutManager instanceof LinearLayoutManager) { - return ((LinearLayoutManager) layoutManager).getReverseLayout(); - } else { - return false; - } + return layoutManager instanceof LinearLayoutManager && ((LinearLayoutManager) layoutManager).getReverseLayout(); } /** @@ -242,6 +223,10 @@ private int getGroupIndex(int position, RecyclerView parent) { protected abstract void setItemOffsets(Rect outRect, int position, RecyclerView parent); + protected enum DividerType { + DRAWABLE, PAINT, COLOR + } + /** * Interface for controlling divider visibility */ @@ -263,7 +248,7 @@ public interface VisibilityProvider { public interface PaintProvider { /** - * Returns {@link android.graphics.Paint} for divider + * Returns {@link Paint} for divider * * @param position Divider position (or group index for GridLayoutManager) * @param parent RecyclerView @@ -320,18 +305,13 @@ public interface SizeProvider { public static class Builder { - private Context mContext; - protected Resources mResources; + final Resources mResources; + private final Context mContext; private PaintProvider mPaintProvider; private ColorProvider mColorProvider; private DrawableProvider mDrawableProvider; private SizeProvider mSizeProvider; - private VisibilityProvider mVisibilityProvider = new VisibilityProvider() { - @Override - public boolean shouldHideDivider(int position, RecyclerView parent) { - return false; - } - }; + private VisibilityProvider mVisibilityProvider = (position, parent) -> false; private boolean mShowLastDivider = false; private boolean mPositionInsideItem = false; @@ -341,12 +321,7 @@ public Builder(Context context) { } public T paint(final Paint paint) { - return paintProvider(new PaintProvider() { - @Override - public Paint dividerPaint(int position, RecyclerView parent) { - return paint; - } - }); + return paintProvider((position, parent) -> paint); } public T paintProvider(PaintProvider provider) { @@ -355,12 +330,7 @@ public T paintProvider(PaintProvider provider) { } public T color(final int color) { - return colorProvider(new ColorProvider() { - @Override - public int dividerColor(int position, RecyclerView parent) { - return color; - } - }); + return colorProvider((position, parent) -> color); } public T colorResId(@ColorRes int colorId) { @@ -377,12 +347,7 @@ public T drawable(@DrawableRes int id) { } public T drawable(final Drawable drawable) { - return drawableProvider(new DrawableProvider() { - @Override - public Drawable drawableProvider(int position, RecyclerView parent) { - return drawable; - } - }); + return drawableProvider((position, parent) -> drawable); } public T drawableProvider(DrawableProvider provider) { @@ -391,12 +356,7 @@ public T drawableProvider(DrawableProvider provider) { } public T size(final int size) { - return sizeProvider(new SizeProvider() { - @Override - public int dividerSize(int position, RecyclerView parent) { - return size; - } - }); + return sizeProvider((position, parent) -> size); } public T sizeResId(@DimenRes int sizeId) { @@ -423,7 +383,7 @@ public T positionInsideItem(boolean positionInsideItem) { return (T) this; } - protected void checkBuilderParams() { + void checkBuilderParams() { if (mPaintProvider != null) { if (mColorProvider != null) { throw new IllegalArgumentException( diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FooterAdapter.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FooterAdapter.java index 1b532a0b..6cd1646a 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FooterAdapter.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FooterAdapter.java @@ -1,32 +1,38 @@ package cn.finalteam.rxgalleryfinal.ui.widget; -import android.support.v7.widget.RecyclerView; +import androidx.recyclerview.widget.RecyclerView; import android.view.View; import android.view.ViewGroup; /** * Desction:footer适配器 - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/5/21 下午3:59 */ public class FooterAdapter extends RecyclerView.Adapter { private static final int ITEM_VIEW_TYPE_FOOTER = 0; private static final int ITEM_VIEW_TYPE_ITEM = 1; - private RecyclerView.Adapter mAdapter; - private View mFooterView; + private final RecyclerView.Adapter mAdapter; + private final View mFooterView; private OnItemClickListener mOnItemClickListener; public FooterAdapter(RecyclerView.Adapter adapter, View footerView) { this.mAdapter = adapter; - this.mAdapter.registerAdapterDataObserver(mDataObserver); + this.mAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() { + @Override + public void onChanged() { + super.onChanged(); + notifyDataSetChanged(); + } + }); this.mFooterView = footerView; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - if(viewType == ITEM_VIEW_TYPE_FOOTER) { + if (viewType == ITEM_VIEW_TYPE_FOOTER) { return new FooterViewHolder(mFooterView); } return mAdapter.onCreateViewHolder(parent, viewType); @@ -34,9 +40,8 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { - if(isFooter(position)) { - } else { - if(mOnItemClickListener != null) { + if (!isFooter(position)) { + if (mOnItemClickListener != null) { holder.itemView.setOnClickListener(v -> mOnItemClickListener.onItemClick(holder, position)); } mAdapter.onBindViewHolder(holder, position); @@ -45,16 +50,11 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { /** * 设置Item点击事件 - * @param listener */ public void setOnItemClickListener(OnItemClickListener listener) { this.mOnItemClickListener = listener; } - public interface OnItemClickListener{ - void onItemClick(RecyclerView.ViewHolder holder, int position); - } - @Override public int getItemCount() { return mAdapter.getItemCount() + 1; @@ -62,26 +62,22 @@ public int getItemCount() { @Override public int getItemViewType(int position) { - return isFooter(position)?ITEM_VIEW_TYPE_FOOTER:ITEM_VIEW_TYPE_ITEM; + return isFooter(position) ? ITEM_VIEW_TYPE_FOOTER : ITEM_VIEW_TYPE_ITEM; } public boolean isFooter(int position) { return position == getItemCount() - 1; } - class FooterViewHolder extends RecyclerView.ViewHolder{ + public interface OnItemClickListener { + void onItemClick(RecyclerView.ViewHolder holder, int position); + } + + class FooterViewHolder extends RecyclerView.ViewHolder { public FooterViewHolder(View itemView) { super(itemView); } } - private RecyclerView.AdapterDataObserver mDataObserver = new RecyclerView.AdapterDataObserver() { - @Override - public void onChanged() { - super.onChanged(); - notifyDataSetChanged(); - } - }; - } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/HorizontalDividerItemDecoration.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/HorizontalDividerItemDecoration.java index 3bcab36b..b7afd57e 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/HorizontalDividerItemDecoration.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/HorizontalDividerItemDecoration.java @@ -3,19 +3,19 @@ import android.content.Context; import android.graphics.Rect; import android.graphics.drawable.Drawable; -import android.support.annotation.DimenRes; -import android.support.v4.view.ViewCompat; -import android.support.v7.widget.RecyclerView; +import androidx.annotation.DimenRes; +import androidx.core.view.ViewCompat; +import androidx.recyclerview.widget.RecyclerView; import android.view.View; /** - * Created by yqritc on 2015/01/15. + * by yqritc on 2015/01/15. */ public class HorizontalDividerItemDecoration extends FlexibleDividerDecoration { - private MarginProvider mMarginProvider; + private final MarginProvider mMarginProvider; - protected HorizontalDividerItemDecoration(Builder builder) { + private HorizontalDividerItemDecoration(Builder builder) { super(builder); mMarginProvider = builder.mMarginProvider; } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/MarginDecoration.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/MarginDecoration.java index e3ab94ea..18469963 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/MarginDecoration.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/MarginDecoration.java @@ -2,13 +2,13 @@ import android.content.Context; import android.graphics.Rect; -import android.support.v7.widget.RecyclerView; +import androidx.recyclerview.widget.RecyclerView; import android.view.View; import cn.finalteam.rxgalleryfinal.R; public class MarginDecoration extends RecyclerView.ItemDecoration { - private int margin; + private final int margin; public MarginDecoration(Context context) { margin = context.getResources().getDimensionPixelSize(R.dimen.gallery_grid_item_margin); diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/RecyclerImageView.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/RecyclerImageView.java deleted file mode 100644 index 8dd7771b..00000000 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/RecyclerImageView.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.finalteam.rxgalleryfinal.ui.widget; - -import android.content.Context; -import android.util.AttributeSet; - -/** - * Desction: - * Author:pengjianbo - * Date:16/6/3 下午8:10 - */ -public class RecyclerImageView extends SquareImageView { - - public RecyclerImageView(Context context) { - super(context); - } - - public RecyclerImageView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public RecyclerImageView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - -// @Override -// protected void onDetachedFromWindow() { -// super.onDetachedFromWindow(); -// setImageDrawable(null); -// } - -} diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/RecyclerViewFinal.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/RecyclerViewFinal.java index 1fb848fc..3c738568 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/RecyclerViewFinal.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/RecyclerViewFinal.java @@ -1,16 +1,16 @@ package cn.finalteam.rxgalleryfinal.ui.widget; +import android.annotation.SuppressLint; import android.content.Context; import android.os.SystemClock; -import android.support.v7.widget.GridLayoutManager; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.StaggeredGridLayoutManager; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; -import android.widget.Adapter; import android.widget.ProgressBar; import android.widget.TextView; @@ -19,52 +19,69 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/3/7 下午6:40 */ public class RecyclerViewFinal extends RecyclerView { /** - * 加载更多lock + * 是否可以加载跟多 */ - private boolean mLoadMoreLock; + private boolean mHasLoadMore; /** - * 是否可以加载跟多 + * 加载更多lock */ - boolean mHasLoadMore; - + private boolean mLoadMoreLock; /** * 加载更多事件回调 */ private OnLoadMoreListener mOnLoadMoreListener; - /** * emptyview */ private View mEmptyView; + /** + * 刷新数据时停止滑动,避免出现数组下标越界问题 + */ + private final AdapterDataObserver mDataObserver = new AdapterDataObserver() { + @Override + public void onChanged() { + Adapter adapter = getAdapter(); + if (adapter != null && mEmptyView != null) { + if (adapter.getItemCount() == 0) { + mEmptyView.setVisibility(View.VISIBLE); + setVisibility(View.GONE); + } else { + mEmptyView.setVisibility(View.GONE); + setVisibility(View.VISIBLE); + } + } + dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_CANCEL, 0, 0, 0)); + } + }; private FooterAdapter mFooterViewAdapter; - private TextView mTvMessage; private ProgressBar mPbLoading; private View mFooterView; public RecyclerViewFinal(Context context) { super(context); - init(context, null); + init(context); } public RecyclerViewFinal(Context context, AttributeSet attrs) { super(context, attrs); - init(context, attrs); + init(context); } public RecyclerViewFinal(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - init(context, attrs); + init(context); } - private void init(Context context, AttributeSet attrs) { + @SuppressLint("InflateParams") + private void init(Context context) { mFooterView = LayoutInflater.from(context).inflate(R.layout.gallery_loading_view_final_footer_default, null); mPbLoading = (ProgressBar) mFooterView.findViewById(R.id.pb_loading); mTvMessage = (TextView) mFooterView.findViewById(R.id.tv_loading_msg); @@ -73,18 +90,17 @@ private void init(Context context, AttributeSet attrs) { addOnScrollListener(new RecyclerViewOnScrollListener()); } - Adapter adapter; @Override public void setAdapter(Adapter adapter) { - this.adapter = adapter; try { adapter.unregisterAdapterDataObserver(mDataObserver); - } catch (Exception e){} + } catch (Exception ignored) { + } adapter.registerAdapterDataObserver(mDataObserver); mFooterViewAdapter = new FooterAdapter(adapter, mFooterView); - if(getLayoutManager() != null) { + if (getLayoutManager() != null) { GridLayoutManager manager = (GridLayoutManager) getLayoutManager(); manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override @@ -99,7 +115,6 @@ public int getSpanSize(int position) { /** * 设置recyclerview emptyview - * @param emptyView */ public void setEmptyView(View emptyView) { this.mEmptyView = emptyView; @@ -108,7 +123,7 @@ public void setEmptyView(View emptyView) { /** * 没有很多了 */ - void showNoMoreUI() { + private void showNoMoreUI() { mLoadMoreLock = false; mPbLoading.setVisibility(View.GONE); mTvMessage.setText(R.string.gallery_loading_view_no_more); @@ -117,7 +132,7 @@ void showNoMoreUI() { /** * 显示默认UI */ - void showNormalUI() { + private void showNormalUI() { mLoadMoreLock = false; mPbLoading.setVisibility(View.GONE); mTvMessage.setText(R.string.gallery_loading_view_click_loading_more); @@ -126,14 +141,13 @@ void showNormalUI() { /** * 显示加载中UI */ - void showLoadingUI(){ + private void showLoadingUI() { mPbLoading.setVisibility(View.VISIBLE); mTvMessage.setText(R.string.gallery_loading_view_loading); } /** * 是否有更多 - * @param hasLoadMore */ public void setHasLoadMore(boolean hasLoadMore) { mHasLoadMore = hasLoadMore; @@ -146,7 +160,6 @@ public void setHasLoadMore(boolean hasLoadMore) { /** * 设置加载更多事件回调 - * @param loadMoreListener */ public void setOnLoadMoreListener(OnLoadMoreListener loadMoreListener) { this.mOnLoadMoreListener = loadMoreListener; @@ -164,8 +177,8 @@ public void onLoadMoreComplete() { /** * 加载更多 */ - void executeLoadMore() { - if(!mLoadMoreLock && mHasLoadMore) { + private void executeLoadMore() { + if (!mLoadMoreLock && mHasLoadMore) { if (mOnLoadMoreListener != null) { mOnLoadMoreListener.loadMore(); } @@ -175,7 +188,7 @@ void executeLoadMore() { } public void setFooterViewHide(boolean footerViewHide) { - if(footerViewHide) { + if (footerViewHide) { mFooterView.setVisibility(View.GONE); } else { mFooterView.setVisibility(View.VISIBLE); @@ -184,12 +197,15 @@ public void setFooterViewHide(boolean footerViewHide) { /** * 设置OnItemClickListener - * @param listener */ public void setOnItemClickListener(FooterAdapter.OnItemClickListener listener) { mFooterViewAdapter.setOnItemClickListener(listener); } + public interface OnLoadMoreListener { + void loadMore(); + } + /** * 滚动到底部自动加载更多数据 */ @@ -216,10 +232,10 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { LayoutManager layoutManager = recyclerView.getLayoutManager(); - if (layoutManager instanceof LinearLayoutManager) { - lastVisibleItemPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition(); - } else if (layoutManager instanceof GridLayoutManager) { + if (layoutManager instanceof GridLayoutManager) { lastVisibleItemPosition = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition(); + } else if (layoutManager instanceof LinearLayoutManager) { + lastVisibleItemPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition(); } else if (layoutManager instanceof StaggeredGridLayoutManager) { StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) layoutManager; if (lastPositions == null) { @@ -241,7 +257,7 @@ public void onScrollStateChanged(RecyclerView recyclerView, int newState) { int visibleItemCount = layoutManager.getChildCount(); int totalItemCount = layoutManager.getItemCount(); if ((visibleItemCount > 0 && currentScrollState == RecyclerView.SCROLL_STATE_IDLE && (lastVisibleItemPosition) >= totalItemCount - 1)) { - if(mHasLoadMore) { + if (mHasLoadMore) { executeLoadMore(); } } @@ -249,9 +265,6 @@ public void onScrollStateChanged(RecyclerView recyclerView, int newState) { /** * 取数组中最大值 - * - * @param lastPositions - * @return */ private int findMax(int[] lastPositions) { int max = lastPositions[0]; @@ -264,30 +277,4 @@ private int findMax(int[] lastPositions) { return max; } } - - public interface OnLoadMoreListener { - void loadMore(); - } - - - /** - * 刷新数据时停止滑动,避免出现数组下标越界问题 - */ - private AdapterDataObserver mDataObserver = new AdapterDataObserver() { - @Override - public void onChanged() { - Adapter adapter = getAdapter(); - if(adapter != null && mEmptyView != null) { - if(adapter.getItemCount() == 0) { - mEmptyView.setVisibility(View.VISIBLE); - setVisibility(View.GONE); - } else { - mEmptyView.setVisibility(View.GONE); - setVisibility(View.VISIBLE); - } - } - - dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_CANCEL, 0, 0, 0)); - } - }; } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/SquareImageView.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/SquareImageView.java index 17b57192..6822079a 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/SquareImageView.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/SquareImageView.java @@ -5,7 +5,7 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/7/9 上午12:53 */ public class SquareImageView extends FixImageView { @@ -22,8 +22,8 @@ public SquareImageView(Context context, AttributeSet attrs, int defStyleAttr) { } @Override - protected void onMeasure( int widthMeasureSpec, int heightMeasureSpec) { - super .onMeasure(widthMeasureSpec, heightMeasureSpec); + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(getMeasuredWidth(), getMeasuredWidth()); //Snap to width } } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/SquareLinearLayout.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/SquareLinearLayout.java index 9949a7c9..0f1bb0c2 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/SquareLinearLayout.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/SquareLinearLayout.java @@ -6,7 +6,7 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/6/17 下午1:48 */ public class SquareLinearLayout extends LinearLayout { @@ -20,8 +20,8 @@ public SquareLinearLayout(Context context, AttributeSet attrs) { } @Override - protected void onMeasure( int widthMeasureSpec, int heightMeasureSpec) { - super .onMeasure(widthMeasureSpec, heightMeasureSpec); + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(getMeasuredWidth(), getMeasuredWidth()); //Snap to width } } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/SquareRelativeLayout.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/SquareRelativeLayout.java index abe75128..bfa53568 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/SquareRelativeLayout.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/SquareRelativeLayout.java @@ -6,7 +6,7 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/6/8 下午4:07 */ public class SquareRelativeLayout extends RelativeLayout { @@ -24,8 +24,8 @@ public SquareRelativeLayout(Context context, AttributeSet attrs, int defStyleAtt } @Override - protected void onMeasure( int widthMeasureSpec, int heightMeasureSpec) { - super .onMeasure(widthMeasureSpec, heightMeasureSpec); + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(getMeasuredWidth(), getMeasuredWidth()); //Snap to width } } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/BitmapUtils.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/BitmapUtils.java index bf127632..4f881d93 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/BitmapUtils.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/BitmapUtils.java @@ -6,14 +6,14 @@ import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.graphics.drawable.Drawable; -import android.media.ExifInterface; import android.media.ThumbnailUtils; import android.net.Uri; import android.os.Build; import android.provider.MediaStore; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.graphics.drawable.DrawableCompat; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.exifinterface.media.ExifInterface; +import androidx.core.graphics.drawable.DrawableCompat; import android.text.TextUtils; import com.yalantis.ucrop.callback.BitmapLoadCallback; @@ -27,7 +27,7 @@ /** * Desction:Bitmap处理工具类,图片压缩、裁剪、选择、存储 - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/5/4 下午5:03 */ public class BitmapUtils { @@ -45,14 +45,10 @@ public static void createVideoThumbnailSmallPath(String thumbnailSaveDir, String /** * 创建视频缩略图 - * @param thumbnailSaveDir - * @param originalPath - * @param scale - * @return */ public static void createVideoThumbnail(String thumbnailSaveDir, String originalPath, int scale) { Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(originalPath, MediaStore.Video.Thumbnails.MINI_KIND); - if(bitmap == null){ + if (bitmap == null) { return; } int originalImageWidth = bitmap.getWidth(); @@ -60,7 +56,7 @@ public static void createVideoThumbnail(String thumbnailSaveDir, String original int maxValue = Math.max(originalImageWidth, originalImageHeight); BufferedInputStream bufferedInputStream = null; FileOutputStream fileOutputStream = null; - File targetFile = null; + File targetFile; try { BitmapFactory.Options options = new BitmapFactory.Options(); if (maxValue > 3000) { @@ -68,9 +64,9 @@ public static void createVideoThumbnail(String thumbnailSaveDir, String original } else if (maxValue > 2000 && maxValue <= 3000) { options.inSampleSize = scale * 4; } else if (maxValue > 1500 && maxValue <= 2000) { - options.inSampleSize = (int)(scale * 2.5); + options.inSampleSize = (int) (scale * 2.5); } else if (maxValue > 1000 && maxValue <= 1500) { - options.inSampleSize = (int)(scale * 1.3); + options.inSampleSize = (int) (scale * 1.3); // } else if (maxValue > 400 && maxValue <= 1000) { // options.inSampleSize = scale * 2; } else { @@ -96,10 +92,10 @@ public static void createVideoThumbnail(String thumbnailSaveDir, String original fileOutputStream = new FileOutputStream(targetFile); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream); - } catch (Exception e){ + } catch (Exception e) { Logger.e(e); } finally { - if(bitmap != null && !bitmap.isRecycled()){ + if (!bitmap.isRecycled()) { bitmap.recycle(); } @@ -111,28 +107,30 @@ public static void createVideoThumbnail(String thumbnailSaveDir, String original /** * 创建大缩略图 - * @param targetFile 保存目标文件 + * + * @param targetFile 保存目标文件 * @param originalPath 图片地址 - * */ + */ public static void createThumbnailBig(File targetFile, String originalPath) { compressAndSaveImage(targetFile, originalPath, THUMBNAIL_BIG); } /** * 创建小缩略图 - * @param targetFile 保存目标文件 + * + * @param targetFile 保存目标文件 * @param originalPath 图片地址 - * */ + */ public static void createThumbnailSmall(File targetFile, String originalPath) { compressAndSaveImage(targetFile, originalPath, THUMBNAIL_SMALL); } /** * 图片压缩并且存储 - * @param targetFile 保存目标文件 + * + * @param targetFile 保存目标文件 * @param originalPath 图片地址 - * @param scale 图片缩放值 - * @return + * @param scale 图片缩放值 */ public static void compressAndSaveImage(File targetFile, String originalPath, int scale) { @@ -176,9 +174,9 @@ public static void compressAndSaveImage(File targetFile, String originalPath, in } else if (maxValue > 2000 && maxValue <= 3000) { options.inSampleSize = scale * 4; } else if (maxValue > 1500 && maxValue <= 2000) { - options.inSampleSize = (int)(scale * 2.5); + options.inSampleSize = (int) (scale * 2.5); } else if (maxValue > 1000 && maxValue <= 1500) { - options.inSampleSize = (int)(scale * 1.3); + options.inSampleSize = (int) (scale * 1.3); // } else if (maxValue > 400 && maxValue <= 1000) { // options.inSampleSize = scale * 2; } else { @@ -191,7 +189,7 @@ public static void compressAndSaveImage(File targetFile, String originalPath, in bitmap = BitmapFactory.decodeStream(bufferedInputStream, null, options); bufferedInputStream.close(); - if(bitmap == null){ + if (bitmap == null) { return; } String extension = FilenameUtils.getExtension(originalPath); @@ -209,10 +207,10 @@ public static void compressAndSaveImage(File targetFile, String originalPath, in } //5、保存图片 - if(TextUtils.equals(extension.toLowerCase(), "jpg") + if (TextUtils.equals(extension.toLowerCase(), "jpg") || TextUtils.equals(extension.toLowerCase(), "jpeg")) { bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream); - } else if(TextUtils.equals(extension.toLowerCase(), "webp") + } else if (TextUtils.equals(extension.toLowerCase(), "webp") && Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { bitmap.compress(Bitmap.CompressFormat.WEBP, 100, fileOutputStream); } else { @@ -224,7 +222,7 @@ public static void compressAndSaveImage(File targetFile, String originalPath, in IOUtils.close(bufferedInputStream); IOUtils.flush(fileOutputStream); IOUtils.close(fileOutputStream); - if(bitmap != null && bitmap.isRecycled()){ + if (bitmap != null && bitmap.isRecycled()) { bitmap.recycle(); } } @@ -232,29 +230,16 @@ public static void compressAndSaveImage(File targetFile, String originalPath, in /** * 获取一张图片在手机上的方向值 - * @param uri - * @return - * @throws IOException */ - public static int getImageOrientation(String uri) { - if(!new File(uri).exists()){ + public static int getImageOrientation(String uri) throws IOException { + if (!new File(uri).exists()) { return 0; } - try { - ExifInterface exif = new ExifInterface(uri); - int orientation = exif.getAttributeInt( - ExifInterface.TAG_ORIENTATION, - ExifInterface.ORIENTATION_NORMAL); - return orientation; - }catch (Exception e){} - return 0; + return new ExifInterface(uri).getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); } /** * Drawable着色工具 - * @param drawable - * @param colors - * @return */ public static Drawable tintDrawable(Drawable drawable, ColorStateList colors) { final Drawable wrappedDrawable = DrawableCompat.wrap(drawable); @@ -269,12 +254,6 @@ public void decodeBitmapInBackground(@NonNull Context context, @NonNull Uri uri, /** * 获取图片Bitmap - * @param context - * @param uri - * @param outputUri - * @param requiredWidth - * @param requiredHeight - * @param loadCallback */ public void decodeBitmapInBackground(@NonNull Context context, @NonNull Uri uri, @Nullable Uri outputUri, int requiredWidth, int requiredHeight, BitmapLoadCallback loadCallback) { @@ -283,12 +262,6 @@ public void decodeBitmapInBackground(@NonNull Context context, @NonNull Uri uri, /** * 图片压缩旋转 - * @param context - * @param uri - * @param outputUri - * @param requiredWidth - * @param requiredHeight - * @param loadCallback */ public void rotateImage(@NonNull Context context, @NonNull Uri uri, @Nullable Uri outputUri, int requiredWidth, int requiredHeight, BitmapLoadCallback loadCallback) { diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/CameraUtils.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/CameraUtils.java index c895d390..b6a06239 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/CameraUtils.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/CameraUtils.java @@ -5,22 +5,17 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/6/3 下午8:28 */ public class CameraUtils { /** * 判断设备是否有摄像头 - * @param context - * @return */ public static boolean hasCamera(Context context) { PackageManager packageManager = context.getPackageManager(); - if(!packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)){ - return false; - } + return packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY); - return true; } } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/DeviceUtils.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/DeviceUtils.java index 80abbe90..b40989f9 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/DeviceUtils.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/DeviceUtils.java @@ -6,7 +6,7 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/8/8 下午11:05 */ public class DeviceUtils { diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/EmptyViewUtils.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/EmptyViewUtils.java index d6f7bd41..6824e33a 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/EmptyViewUtils.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/EmptyViewUtils.java @@ -7,13 +7,13 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/5/14 下午7:26 */ public class EmptyViewUtils { public static void showLoading(ViewGroup emptyView) { - if(emptyView == null) { + if (emptyView == null) { return; } ProgressBar pbLoading = (ProgressBar) emptyView.getChildAt(0); @@ -23,7 +23,7 @@ public static void showLoading(ViewGroup emptyView) { } public static void showMessage(ViewGroup emptyView, String msg) { - if(emptyView == null) { + if (emptyView == null) { return; } ProgressBar pbLoading = (ProgressBar) emptyView.getChildAt(0); 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..ade8ccb8 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/FileUtils.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/FileUtils.java @@ -1,10 +1,44 @@ package cn.finalteam.rxgalleryfinal.utils; +import android.app.Activity; +import android.content.ContentValues; +import android.net.Uri; +import android.os.Build; +import android.provider.MediaStore; + +import com.zhy.base.fileprovider.FileProvider7; + +import java.io.File; + /** * Desction:文件工具类 - * Author:pengjianbo - * Date:16/5/6 下午5:45 + * Author:dujinyang */ public class FileUtils { + /** + * 验证是否是图片路径 + */ + public static int existImageDir(String dir) { + return dir.trim().lastIndexOf("."); + } + + public static Uri fromFile(Activity activity, File file) { + + Uri imageUri = null; + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { + imageUri = Uri.fromFile(file); + } else { + //兼容android7.0 使用共享文件的形式 + ContentValues contentValues = new ContentValues(1); + contentValues.put(MediaStore.Images.Media.DATA, file.getAbsolutePath()); + + imageUri = activity.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues); + } + return imageUri; + } + + public static Uri fromFile7(Activity activity, File file) { + return FileProvider7.getUriForFile(activity, file); + } } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/FilenameUtils.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/FilenameUtils.java index bee0a139..7b8f963d 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/FilenameUtils.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/FilenameUtils.java @@ -66,12 +66,14 @@ public class FilenameUtils { /** * The extension separator character. + * * @since 1.4 */ public static final char EXTENSION_SEPARATOR = '.'; /** * The extension separator String. + * * @since 1.4 */ public static final String EXTENSION_SEPARATOR_STR = Character.toString(EXTENSION_SEPARATOR); @@ -95,6 +97,7 @@ public class FilenameUtils { * The separator character that is the opposite of the system separator. */ private static final char OTHER_SEPARATOR; + static { if (isSystemWindows()) { OTHER_SEPARATOR = UNIX_SEPARATOR; @@ -111,6 +114,7 @@ public FilenameUtils() { } //----------------------------------------------------------------------- + /** * Determines if Windows file system is in use. * @@ -121,10 +125,11 @@ static boolean isSystemWindows() { } //----------------------------------------------------------------------- + /** * Checks if the character is a separator. * - * @param ch the character to check + * @param ch the character to check * @return true if it is a separator character */ private static boolean isSeparator(char ch) { @@ -132,6 +137,7 @@ private static boolean isSeparator(char ch) { } //----------------------------------------------------------------------- + /** * Normalizes a path, removing double and single dot path steps. *

@@ -169,12 +175,13 @@ private static boolean isSeparator(char ch) { * * (Note the file separator returned will be correct for Windows/Unix) * - * @param filename the filename to normalize, null returns null + * @param filename the filename to normalize, null returns null * @return the normalized filename, or null if invalid */ public static String normalize(String filename) { return doNormalize(filename, SYSTEM_SEPARATOR, true); } + /** * Normalizes a path, removing double and single dot path steps. *

@@ -213,9 +220,9 @@ public static String normalize(String filename) { * The output will be the same on both Unix and Windows including * the separator character. * - * @param filename the filename to normalize, null returns null + * @param filename the filename to normalize, null returns null * @param unixSeparator {@code true} if a unix separator should - * be used or {@code false} if a windows separator should be used. + * be used or {@code false} if a windows separator should be used. * @return the normalized filename, or null if invalid * @since 2.0 */ @@ -225,6 +232,7 @@ public static String normalize(String filename, boolean unixSeparator) { } //----------------------------------------------------------------------- + /** * Normalizes a path, removing double and single dot path steps, * and removing any final directory separator. @@ -263,7 +271,7 @@ public static String normalize(String filename, boolean unixSeparator) { * * (Note the file separator returned will be correct for Windows/Unix) * - * @param filename the filename to normalize, null returns null + * @param filename the filename to normalize, null returns null * @return the normalized filename, or null if invalid */ public static String normalizeNoEndSeparator(String filename) { @@ -307,9 +315,9 @@ public static String normalizeNoEndSeparator(String filename) { * ~/../bar --> null * * - * @param filename the filename to normalize, null returns null + * @param filename the filename to normalize, null returns null * @param unixSeparator {@code true} if a unix separator should - * be used or {@code false} if a windows separtor should be used. + * be used or {@code false} if a windows separtor should be used. * @return the normalized filename, or null if invalid * @since 2.0 */ @@ -321,9 +329,9 @@ public static String normalizeNoEndSeparator(String filename, boolean unixSepara /** * Internal method to perform the normalization. * - * @param filename the filename - * @param separator The separator character to use - * @param keepSeparator true to keep the final separator + * @param filename the filename + * @param separator The separator character to use + * @param keepSeparator true to keep the final separator * @return the normalized filename */ private static String doNormalize(String filename, char separator, boolean keepSeparator) { @@ -374,7 +382,7 @@ private static String doNormalize(String filename, char separator, boolean keepS lastIsDirectory = true; } System.arraycopy(array, i + 1, array, i - 1, size - i); - size -=2; + size -= 2; i--; } } @@ -391,7 +399,7 @@ private static String doNormalize(String filename, char separator, boolean keepS lastIsDirectory = true; } int j; - for (j = i - 4 ; j >= prefix; j--) { + for (j = i - 4; j >= prefix; j--) { if (array[j] == separator) { // remove b/../ from a/b/../c System.arraycopy(array, i + 1, array, j + 1, size - i); @@ -420,6 +428,7 @@ private static String doNormalize(String filename, char separator, boolean keepS } //----------------------------------------------------------------------- + /** * Concatenates a filename to a base path using normal command line style rules. *

@@ -456,8 +465,8 @@ private static String doNormalize(String filename, char separator, boolean keepS * the name will be built into the concatenated path. If this might be a problem, * use {@link #getFullPath(String)} on the base path argument. * - * @param basePath the base path to attach to, always treated as a path - * @param fullFilenameToAdd the filename (or path) to attach to the base + * @param basePath the base path to attach to, always treated as a path + * @param fullFilenameToAdd the filename (or path) to attach to the base * @return the concatenated path, or null if invalid */ public static String concat(String basePath, String fullFilenameToAdd) { @@ -484,10 +493,11 @@ public static String concat(String basePath, String fullFilenameToAdd) { } //----------------------------------------------------------------------- + /** * Converts all separators to the Unix separator of forward slash. * - * @param path the path to be changed, null ignored + * @param path the path to be changed, null ignored * @return the updated path */ public static String separatorsToUnix(String path) { @@ -500,7 +510,7 @@ public static String separatorsToUnix(String path) { /** * Converts all separators to the Windows separator of backslash. * - * @param path the path to be changed, null ignored + * @param path the path to be changed, null ignored * @return the updated path */ public static String separatorsToWindows(String path) { @@ -513,7 +523,7 @@ public static String separatorsToWindows(String path) { /** * Converts all separators to the system separator. * - * @param path the path to be changed, null ignored + * @param path the path to be changed, null ignored * @return the updated path */ public static String separatorsToSystem(String path) { @@ -528,6 +538,7 @@ public static String separatorsToSystem(String path) { } //----------------------------------------------------------------------- + /** * Returns the length of the filename prefix, such as C:/ or ~/. *

@@ -556,7 +567,7 @@ public static String separatorsToSystem(String path) { * The output will be the same irrespective of the machine that the code is running on. * ie. both Unix and Windows prefixes are matched regardless. * - * @param filename the filename to find the prefix in, null returns -1 + * @param filename the filename to find the prefix in, null returns -1 * @return the length of the prefix, -1 if invalid or null */ public static int getPrefixLength(String filename) { @@ -591,7 +602,7 @@ public static int getPrefixLength(String filename) { if (ch1 == ':') { ch0 = Character.toUpperCase(ch0); if (ch0 >= 'A' && ch0 <= 'Z') { - if (len == 2 || isSeparator(filename.charAt(2)) == false) { + if (len == 2 || !isSeparator(filename.charAt(2))) { return 2; } return 3; @@ -621,7 +632,7 @@ public static int getPrefixLength(String filename) { *

* The output will be the same irrespective of the machine that the code is running on. * - * @param filename the filename to find the last path separator in, null returns -1 + * @param filename the filename to find the last path separator in, null returns -1 * @return the index of the last separator character, or -1 if there * is no such character */ @@ -643,7 +654,7 @@ public static int indexOfLastSeparator(String filename) { *

* The output will be the same irrespective of the machine that the code is running on. * - * @param filename the filename to find the last path separator in, null returns -1 + * @param filename the filename to find the last path separator in, null returns -1 * @return the index of the last separator character, or -1 if there * is no such character */ @@ -657,6 +668,7 @@ public static int indexOfExtension(String filename) { } //----------------------------------------------------------------------- + /** * Gets the prefix from a full filename, such as C:/ * or ~/. @@ -683,7 +695,7 @@ public static int indexOfExtension(String filename) { * The output will be the same irrespective of the machine that the code is running on. * ie. both Unix and Windows prefixes are matched regardless. * - * @param filename the filename to query, null returns null + * @param filename the filename to query, null returns null * @return the prefix of the file, null if invalid */ public static String getPrefix(String filename) { @@ -719,7 +731,7 @@ public static String getPrefix(String filename) { * This method drops the prefix from the result. * See {@link #getFullPath(String)} for the method that retains the prefix. * - * @param filename the filename to query, null returns null + * @param filename the filename to query, null returns null * @return the path of the file, an empty string if none exists, null if invalid */ public static String getPath(String filename) { @@ -746,7 +758,7 @@ public static String getPath(String filename) { * This method drops the prefix from the result. * See {@link #getFullPathNoEndSeparator(String)} for the method that retains the prefix. * - * @param filename the filename to query, null returns null + * @param filename the filename to query, null returns null * @return the path of the file, an empty string if none exists, null if invalid */ public static String getPathNoEndSeparator(String filename) { @@ -756,8 +768,8 @@ public static String getPathNoEndSeparator(String filename) { /** * Does the work of getting the path. * - * @param filename the filename - * @param separatorAdd 0 to omit the end separator, 1 to return it + * @param filename the filename + * @param separatorAdd 0 to omit the end separator, 1 to return it * @return the path */ private static String doGetPath(String filename, int separatorAdd) { @@ -769,7 +781,7 @@ private static String doGetPath(String filename, int separatorAdd) { return null; } int index = indexOfLastSeparator(filename); - int endIndex = index+separatorAdd; + int endIndex = index + separatorAdd; if (prefix >= filename.length() || index < 0 || prefix >= endIndex) { return ""; } @@ -798,7 +810,7 @@ private static String doGetPath(String filename, int separatorAdd) { *

* The output will be the same irrespective of the machine that the code is running on. * - * @param filename the filename to query, null returns null + * @param filename the filename to query, null returns null * @return the path of the file, an empty string if none exists, null if invalid */ public static String getFullPath(String filename) { @@ -828,7 +840,7 @@ public static String getFullPath(String filename) { *

* The output will be the same irrespective of the machine that the code is running on. * - * @param filename the filename to query, null returns null + * @param filename the filename to query, null returns null * @return the path of the file, an empty string if none exists, null if invalid */ public static String getFullPathNoEndSeparator(String filename) { @@ -838,8 +850,8 @@ public static String getFullPathNoEndSeparator(String filename) { /** * Does the work of getting the path. * - * @param filename the filename - * @param includeSeparator true to include the end separator + * @param filename the filename + * @param includeSeparator true to include the end separator * @return the path */ private static String doGetFullPath(String filename, boolean includeSeparator) { @@ -861,7 +873,7 @@ private static String doGetFullPath(String filename, boolean includeSeparator) { if (index < 0) { return filename.substring(0, prefix); } - int end = index + (includeSeparator ? 1 : 0); + int end = index + (includeSeparator ? 1 : 0); if (end == 0) { end++; } @@ -882,7 +894,7 @@ private static String doGetFullPath(String filename, boolean includeSeparator) { *

* The output will be the same irrespective of the machine that the code is running on. * - * @param filename the filename to query, null returns null + * @param filename the filename to query, null returns null * @return the name of the file without the path, or an empty string if none exists */ public static String getName(String filename) { @@ -924,6 +936,7 @@ public static String getExtension(String filename) { } //----------------------------------------------------------------------- + /** * Checks whether the extension of the filename is that specified. *

@@ -932,7 +945,7 @@ public static String getExtension(String filename) { * The extension check is case-sensitive on all platforms. * * @param filename the filename to query, null returns false - * @param extension the extension to check for, null or empty checks for no extension + * @param extension the extension to check for, null or empty checks for no extension * @return true if the filename has the specified extension */ public static boolean isExtension(String filename, String extension) { @@ -953,8 +966,8 @@ public static boolean isExtension(String filename, String extension) { * after the last dot. There must be no directory separator after the dot. * The extension check is case-sensitive on all platforms. * - * @param filename the filename to query, null returns false - * @param extensions the extensions to check for, null checks for no extension + * @param filename the filename to query, null returns false + * @param extensions the extensions to check for, null checks for no extension * @return true if the filename is one of the extensions */ public static boolean isExtension(String filename, String[] extensions) { @@ -980,8 +993,8 @@ public static boolean isExtension(String filename, String[] extensions) { * after the last dot. There must be no directory separator after the dot. * The extension check is case-sensitive on all platforms. * - * @param filename the filename to query, null returns false - * @param extensions the extensions to check for, null checks for no extension + * @param filename the filename to query, null returns false + * @param extensions the extensions to check for, null checks for no extension * @return true if the filename is one of the extensions */ public static boolean isExtension(String filename, Collection extensions) { @@ -1007,7 +1020,7 @@ public static boolean isExtension(String filename, Collection extensions * The text is split by '?' and '*'. * Where multiple '*' occur consecutively they are collapsed into a single '*'. * - * @param text the text to split + * @param text the text to split * @return the array of tokens, never null */ static String[] splitOnTokens(String text) { @@ -1015,11 +1028,11 @@ static String[] splitOnTokens(String text) { // package level so a unit test may run on this if (text.indexOf('?') == -1 && text.indexOf('*') == -1) { - return new String[] { text }; + return new String[]{text}; } char[] array = text.toCharArray(); - ArrayList list = new ArrayList(); + ArrayList list = new ArrayList<>(); StringBuilder buffer = new StringBuilder(); for (int i = 0; i < array.length; i++) { if (array[i] == '?' || array[i] == '*') { @@ -1030,7 +1043,7 @@ static String[] splitOnTokens(String text) { if (array[i] == '?') { list.add("?"); } else if (list.isEmpty() || - i > 0 && list.get(list.size() - 1).equals("*") == false) { + i > 0 && !list.get(list.size() - 1).equals("*")) { list.add("*"); } } else { @@ -1041,7 +1054,7 @@ static String[] splitOnTokens(String text) { list.add(buffer.toString()); } - return list.toArray( new String[ list.size() ] ); + return list.toArray(new String[list.size()]); } } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/IOUtils.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/IOUtils.java index 2caa925e..f3120d25 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/IOUtils.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/IOUtils.java @@ -6,13 +6,13 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/5/7 上午9:45 */ public class IOUtils { public static void close(OutputStream stream) { - if(stream != null) { + if (stream != null) { try { stream.close(); } catch (IOException e) { @@ -22,7 +22,7 @@ public static void close(OutputStream stream) { } public static void close(InputStream stream) { - if(stream != null) { + if (stream != null) { try { stream.close(); } catch (IOException e) { @@ -32,7 +32,7 @@ public static void close(InputStream stream) { } public static void flush(OutputStream stream) { - if(stream != null) { + if (stream != null) { try { stream.flush(); } catch (IOException e) { diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/Logger.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/Logger.java index 36ec2e5b..aeff1bf4 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/Logger.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/Logger.java @@ -6,40 +6,40 @@ /** * Desction:日志工具 - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/5/23 下午3:12 */ public class Logger { public static final String TAG = "RxGalleryFinal"; - public static final boolean DEBUG = BuildConfig.DEBUG; - - public static void d(String value){ - if(DEBUG) { + public static boolean DEBUG = BuildConfig.DEBUG; + + public static void d(String value) { + if (DEBUG) { Log.d(TAG, value); } } public static void e(String value) { - if(DEBUG) { + if (DEBUG) { Log.e(TAG, value); } } public static void e(Exception value) { - if(DEBUG && value != null) { + if (DEBUG && value != null) { Log.e(TAG, value.getMessage()); } } - public static void i(String value){ - if(DEBUG) { + public static void i(String value) { + if (DEBUG) { Log.i(TAG, value); } } - public static void w(String value){ - if(DEBUG) { + public static void w(String value) { + if (DEBUG) { Log.w(TAG, value); } } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaScanner.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaScanner.java index b56b3ffd..1d66fc0b 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaScanner.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaScanner.java @@ -6,12 +6,11 @@ /** * Desction:媒体扫描工具类 - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/6/8 上午11:36 */ public class MediaScanner { private MediaScannerConnection mediaScanConn = null; - private MusicSannerClient client = null; private String fileType = null; private String[] filePaths = null; private ScanCallback scanCallback; @@ -20,40 +19,17 @@ public class MediaScanner { * 然后调用MediaScanner.scanFile("/sdcard/2.mp3"); */ public MediaScanner(Context context) { - if (client == null) { - client = new MusicSannerClient(); - } + MusicSannerClient client; + client = new MusicSannerClient(); if (mediaScanConn == null) { mediaScanConn = new MediaScannerConnection(context, client); } } - class MusicSannerClient implements MediaScannerConnection.MediaScannerConnectionClient { - @Override - public void onMediaScannerConnected() { - Logger.i("onMediaScannerConnected"); - if (filePaths != null) { - for (String file : filePaths) { - mediaScanConn.scanFile(file, fileType); - } - } - } - - @Override - public void onScanCompleted(String path, Uri uri) { - Logger.i("onScanCompleted"); - mediaScanConn.disconnect(); - if(scanCallback != null) { - scanCallback.onScanCompleted(filePaths); - } - fileType = null; - filePaths = null; - } - } - /** * 扫描文件标签信息 + * * @param filePath 文件路径 * @param fileType 文件类型 */ @@ -68,7 +44,7 @@ public void scanFile(String filePath, String fileType, ScanCallback callback) { /** * @param filePaths 文件路径 - * @param fileType 文件类型 + * @param fileType 文件类型 */ public void scanFile(String[] filePaths, String fileType, ScanCallback callback) { this.filePaths = filePaths; @@ -77,11 +53,34 @@ public void scanFile(String[] filePaths, String fileType, ScanCallback callback) mediaScanConn.connect(); } - public void unScanFile(){ + public void unScanFile() { mediaScanConn.disconnect(); } - public interface ScanCallback{ + public interface ScanCallback { void onScanCompleted(String[] images); } + + private class MusicSannerClient implements MediaScannerConnection.MediaScannerConnectionClient { + @Override + public void onMediaScannerConnected() { + Logger.i("onMediaScannerConnected"); + if (filePaths != null) { + for (String file : filePaths) { + mediaScanConn.scanFile(file, fileType); + } + } + } + + @Override + public void onScanCompleted(String path, Uri uri) { + Logger.i("onScanCompleted"); + mediaScanConn.disconnect(); + if (scanCallback != null) { + scanCallback.onScanCompleted(filePaths); + } + fileType = null; + filePaths = null; + } + } } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaType.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaType.java index e4afd010..8bc97872 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaType.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaType.java @@ -4,11 +4,11 @@ /** * Desction:支持的Media类型 - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/5/5 下午5:03 */ -public enum MediaType implements Serializable{ - JPG,PNG,WEBP,GIF,MP4; +public enum MediaType implements Serializable { + JPG, PNG, WEBP, GIF, MP4; public boolean hasVideo() { return this == MP4; 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..3397165d 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 androidx.annotation.Nullable; +import androidx.exifinterface.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,19 +380,19 @@ 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)); @@ -388,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..b4a61c88 --- /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/OsCompat.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/OsCompat.java index 6e599720..10f5f880 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/OsCompat.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/OsCompat.java @@ -6,15 +6,16 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/7/20 下午4:23 */ public class OsCompat { public static void setBackgroundDrawableCompat(View view, Drawable drawable) { - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN){ + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { view.setBackground(drawable); } else { + //noinspection deprecation view.setBackgroundDrawable(drawable); } } 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..e225d699 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/PermissionCheckUtils.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/PermissionCheckUtils.java @@ -5,57 +5,102 @@ import android.app.Activity; import android.content.pm.PackageManager; import android.os.Build; -import android.support.v4.app.ActivityCompat; -import android.support.v4.content.ContextCompat; -import android.support.v7.app.AlertDialog; +import android.widget.Toast; + +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; +import androidx.appcompat.app.AlertDialog; + +import com.hjq.permissions.OnPermissionCallback; +import com.hjq.permissions.XXPermissions; + +import java.util.List; /** * Desction:权限检查工具 - * Author:pengjianbo + * Author:pengjianbo Dujinyang + * Author:KARL-dujinyang * Date:16/6/1 下午7:40 */ public class PermissionCheckUtils { + /** + * 数组 + */ + public static void checkPermission(Activity activity, String permission, OnPermissionCallback callback) { + + XXPermissions.with(activity) + // 申请单个权限 + .permission(permission) + // 申请多个权限 + //.permission(Permission.Group.CALENDAR) + // 申请安装包权限 + //.permission(Permission.REQUEST_INSTALL_PACKAGES) + // 申请悬浮窗权限 + //.permission(Permission.SYSTEM_ALERT_WINDOW) + // 申请通知栏权限 + //.permission(Permission.NOTIFICATION_SERVICE) + // 申请系统设置权限 + //.permission(Permission.WRITE_SETTINGS) + // 设置权限请求拦截器 + //.interceptor(new PermissionInterceptor()) + // 设置不触发错误检测机制 + //.unchecked() + .request(new OnPermissionCallback() { + + @Override + public void onGranted(List permissions, boolean all) { + if (all) { + //Toast.makeText(activity, "获取权限成功", Toast.LENGTH_SHORT).show(); + } else { + //toast("获取部分权限成功,但部分权限未正常授予"); + //Toast.makeText(activity, "", Toast.LENGTH_SHORT).show(); + } + callback.onGranted(permissions,all); + + } + + @Override + public void onDenied(List permissions, boolean never) { + if (never) { + //toast("被永久拒绝授权,请手动授予录音和日历权限"); + // 如果是被永久拒绝就跳转到应用权限系统设置页面 + XXPermissions.startPermissionActivity(activity, permissions); + } else { + //toast("获取录音和日历权限失败"); + callback.onDenied(permissions,never); + } + + } + }); - 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 (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) { - 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); - }); - AlertDialog alert = alertBuilder.create(); - alert.show(); - } else { - ActivityCompat.requestPermissions(activity, new String[]{permission}, requestCode); - } - return false; - } else { - return true; - } - } else { - return true; - } } /** * 检查是否对sd卡读取授权 - * @param activity - * @param permissionDesc - * @param requestCode - * @return */ @TargetApi(16) - public static boolean checkReadExternalPermission(Activity activity, String permissionDesc, int requestCode) { - return checkPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE, permissionDesc, requestCode); + public static void checkReadExternalPermission(Activity activity, String permissionDesc, int requestCode, OnPermissionCallback callback) { + checkPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE,callback); } + /** + * 检查是否对sd卡读取授权 + */ + @TargetApi(16) + public static void checkWriteExternalPermission(Activity activity, String permissionDesc, int requestCode, OnPermissionCallback callback) { + checkPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE, callback); + } + + /** + * 检查是否对相机读取授权 + */ + @TargetApi(16) + public static void checkCameraPermission(Activity activity, String permissionDesc, int requestCode, OnPermissionCallback callback) { + checkPermission(activity, Manifest.permission.CAMERA, callback); + } + } 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/java/cn/finalteam/rxgalleryfinal/utils/StorageUtils.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/StorageUtils.java index a2edc90d..da98d73d 100755 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/StorageUtils.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/StorageUtils.java @@ -1,5 +1,6 @@ package cn.finalteam.rxgalleryfinal.utils; +import android.annotation.SuppressLint; import android.content.Context; import android.content.pm.PackageManager; import android.os.Environment; @@ -31,7 +32,7 @@ private StorageUtils() { * @param context Application context * @return Cache {@link File directory}.
* NOTE: Can be null in some unpredictable cases (if SD card is unmounted and - * {@link android.content.Context#getCacheDir() Context.getCacheDir()} returns null). + * {@link Context#getCacheDir() Context.getCacheDir()} returns null). */ public static File getCacheDirectory(Context context) { return getCacheDirectory(context, true); @@ -46,7 +47,7 @@ public static File getCacheDirectory(Context context) { * @param preferExternal Whether prefer external location for cache * @return Cache {@link File directory}.
* NOTE: Can be null in some unpredictable cases (if SD card is unmounted and - * {@link android.content.Context#getCacheDir() Context.getCacheDir()} returns null). + * {@link Context#getCacheDir() Context.getCacheDir()} returns null). */ public static File getCacheDirectory(Context context, boolean preferExternal) { File appCacheDir = null; @@ -58,7 +59,7 @@ public static File getCacheDirectory(Context context, boolean preferExternal) { appCacheDir = context.getCacheDir(); } if (appCacheDir == null) { - String cacheDirPath = "/data/data/" + context.getPackageName() + "/cache/"; + @SuppressLint("SdCardPath") String cacheDirPath = "/data/data/" + context.getPackageName() + "/cache/"; Logger.w(String.format("Can't define system cache directory! '%s' will be used.", cacheDirPath)); appCacheDir = new File(cacheDirPath); } @@ -71,8 +72,6 @@ public static boolean existSDcard() { externalStorageState = Environment.getExternalStorageState(); } catch (NullPointerException e) { // (sh)it happens (Issue #660) externalStorageState = ""; - } catch (IncompatibleClassChangeError e) { // (sh)it happens too (Issue #989) - externalStorageState = ""; } return MEDIA_MOUNTED.equals(externalStorageState); } @@ -94,7 +93,7 @@ public static File getIndividualCacheDirectory(Context context) { * created on SD card ("/Android/data/[app_package_name]/cache/uil-images") if card is mounted and app has * appropriate permission. Else - Android defines cache directory on device's file system. * - * @param context Application context + * @param context Application context * @param cacheDir Cache directory path (e.g.: "AppCacheDir", "AppDir/cache/images") * @return Cache {@link File directory} */ diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/ThemeUtils.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/ThemeUtils.java index 4b110364..2dd2d610 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/ThemeUtils.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/ThemeUtils.java @@ -1,20 +1,25 @@ package cn.finalteam.rxgalleryfinal.utils; -import android.annotation.TargetApi; import android.content.Context; +import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.os.Build; -import android.support.annotation.AttrRes; -import android.support.annotation.ColorInt; -import android.support.v4.content.ContextCompat; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.core.content.ContextCompat; import android.text.TextUtils; import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; import android.view.Window; +import android.view.WindowManager; +import android.widget.FrameLayout; /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/7/14 下午7:10 */ public class ThemeUtils { @@ -25,7 +30,7 @@ public static int resolveColor(Context context, @AttrRes int attr) { public static int resolveColor(Context context, @AttrRes int attr, int fallback) { TypedArray a = context.getTheme().obtainStyledAttributes(new int[]{attr}); int color = 0; - if(fallback != 0){ + if (fallback != 0) { color = ContextCompat.getColor(context, fallback); } try { @@ -42,7 +47,7 @@ public static float resolveDimen(Context context, @AttrRes int attr) { public static float resolveDimen(Context context, @AttrRes int attr, int fallback) { TypedArray a = context.getTheme().obtainStyledAttributes(new int[]{attr}); float size = 0; - if(fallback != 0){ + if (fallback != 0) { size = context.getResources().getDimension(fallback); } try { @@ -61,7 +66,7 @@ public static String resolveString(Context context, @AttrRes int attr, int fallb String value; try { String s = a.getString(0); - if(TextUtils.isEmpty(s)){ + if (TextUtils.isEmpty(s)) { s = context.getString(fallback); } value = s; @@ -79,7 +84,7 @@ public static boolean resolveBoolean(Context context, @AttrRes int attr) { public static boolean resolveBoolean(Context context, @AttrRes int attr, int fallback) { TypedArray a = context.getTheme().obtainStyledAttributes(new int[]{attr}); boolean defValue = false; - if(fallback!=0){ + if (fallback != 0) { defValue = context.getResources().getBoolean(fallback); } try { @@ -96,7 +101,7 @@ public static int resolveInteger(Context context, @AttrRes int attr) { public static int resolveInteger(Context context, @AttrRes int attr, int fallback) { TypedArray a = context.getTheme().obtainStyledAttributes(new int[]{attr}); int defValue = 0; - if(fallback!=0){ + if (fallback != 0) { defValue = context.getResources().getInteger(fallback); } try { @@ -126,12 +131,12 @@ public static Drawable resolveDrawable(Context context, @AttrRes int attr) { public static Drawable resolveDrawable(Context context, @AttrRes int attr, int fallback) { TypedArray a = context.getTheme().obtainStyledAttributes(new int[]{attr}); Drawable drawable = null; - if(fallback != 0){ + if (fallback != 0) { drawable = ContextCompat.getDrawable(context, fallback).mutate(); } try { Drawable d = a.getDrawable(0); - if(d != null){ + if (d != null) { drawable = d; } } finally { @@ -150,12 +155,35 @@ public static float applyDimensionDp(Context context, float value) { * * @param color - status-bar color */ - @TargetApi(Build.VERSION_CODES.LOLLIPOP) public static void setStatusBarColor(@ColorInt int color, Window window) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - if (window != null) { + if (window != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { window.setStatusBarColor(color); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + ViewGroup mContentView = (ViewGroup) window.findViewById(Window.ID_ANDROID_CONTENT); + View mChildView = mContentView.getChildAt(0); + if (mChildView != null) { + mChildView.setFitsSystemWindows(true); + } + View statusBarView = new View(window.getContext()); + int statusBarHeight = getStatusBarHeight(window.getContext()); + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, statusBarHeight); + params.gravity = Gravity.TOP; + statusBarView.setLayoutParams(params); + statusBarView.setBackgroundColor(color); + mContentView.addView(statusBarView); } } } + + private static int getStatusBarHeight(Context context) { + int statusBarHeight = 0; + Resources res = context.getResources(); + int resourceId = res.getIdentifier("status_bar_height", "dimen", "android"); + if (resourceId > 0) { + statusBarHeight = res.getDimensionPixelSize(resourceId); + } + return statusBarHeight; + } } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/view/ActivityFragmentView.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/view/ActivityFragmentView.java index 016e79e5..5fe7379c 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/view/ActivityFragmentView.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/view/ActivityFragmentView.java @@ -6,12 +6,14 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/5/14 下午9:56 */ public interface ActivityFragmentView { void showMediaGridFragment(); + void showMediaPageFragment(ArrayList list, int position); + void showMediaPreviewFragment(); } diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/view/MediaGridView.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/view/MediaGridView.java index c75c61ac..8408e5e3 100644 --- a/library/src/main/java/cn/finalteam/rxgalleryfinal/view/MediaGridView.java +++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/view/MediaGridView.java @@ -7,10 +7,11 @@ /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/5/14 上午11:00 */ public interface MediaGridView { void onRequestMediaCallback(List list); + void onRequestBucketCallback(List list); } 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/library/src/main/java/uk/co/senab/photoview/Compat.java b/library/src/main/java/uk/co/senab/photoview/Compat.java index 58c445ae..05f81d70 100755 --- a/library/src/main/java/uk/co/senab/photoview/Compat.java +++ b/library/src/main/java/uk/co/senab/photoview/Compat.java @@ -39,10 +39,7 @@ private static void postOnAnimationJellyBean(View view, Runnable runnable) { } public static int getPointerIndex(int action) { - if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) - return getPointerIndexHoneyComb(action); - else - return getPointerIndexEclair(action); + return getPointerIndexHoneyComb(action); } @SuppressWarnings("deprecation") diff --git a/library/src/main/java/uk/co/senab/photoview/DefaultOnDoubleTapListener.java b/library/src/main/java/uk/co/senab/photoview/DefaultOnDoubleTapListener.java index 27a50e52..06c58be3 100755 --- a/library/src/main/java/uk/co/senab/photoview/DefaultOnDoubleTapListener.java +++ b/library/src/main/java/uk/co/senab/photoview/DefaultOnDoubleTapListener.java @@ -55,7 +55,7 @@ public boolean onSingleTapConfirmed(MotionEvent e) { photoViewAttacher.getOnPhotoTapListener().onPhotoTap(imageView, xResult, yResult); return true; - }else{ + } else { photoViewAttacher.getOnPhotoTapListener().onOutsidePhotoTap(); } } diff --git a/library/src/main/java/uk/co/senab/photoview/IPhotoView.java b/library/src/main/java/uk/co/senab/photoview/IPhotoView.java index 43b01dc2..fcf01518 100755 --- a/library/src/main/java/uk/co/senab/photoview/IPhotoView.java +++ b/library/src/main/java/uk/co/senab/photoview/IPhotoView.java @@ -79,12 +79,32 @@ public interface IPhotoView { @Deprecated float getMinScale(); + /** + * Use {@link #setMinimumScale(float minimumScale)} instead, this will be removed in future + * release + *

 

+ * Sets the minimum scale level. What this value represents depends on the current {@link + * ImageView.ScaleType}. + * + * @param minScale minimum allowed scale + */ + @Deprecated + void setMinScale(float minScale); + /** * @return The current minimum scale level. What this value represents depends on the current * {@link ImageView.ScaleType}. */ float getMinimumScale(); + /** + * Sets the minimum scale level. What this value represents depends on the current {@link + * ImageView.ScaleType}. + * + * @param minimumScale minimum allowed scale + */ + void setMinimumScale(float minimumScale); + /** * Use {@link #getMediumScale()} instead, this will be removed in future release * @@ -94,6 +114,18 @@ public interface IPhotoView { @Deprecated float getMidScale(); + /** + * Use {@link #setMediumScale(float mediumScale)} instead, this will be removed in future + * release + *

 

+ * Sets the middle scale level. What this value represents depends on the current {@link + * ImageView.ScaleType}. + * + * @param midScale medium scale preset + */ + @Deprecated + void setMidScale(float midScale); + /** * @return The current medium scale level. What this value represents depends on the current * {@link ImageView.ScaleType}. @@ -101,100 +133,84 @@ public interface IPhotoView { float getMediumScale(); /** - * Use {@link #getMaximumScale()} instead, this will be removed in future release + * Sets the medium scale level. What this value represents depends on the current {@link ImageView.ScaleType}. * - * @return The current maximum scale level. What this value represents depends on the current - * {@link ImageView.ScaleType}. + * @param mediumScale medium scale preset */ - @Deprecated - float getMaxScale(); + void setMediumScale(float mediumScale); /** + * Use {@link #getMaximumScale()} instead, this will be removed in future release + * * @return The current maximum scale level. What this value represents depends on the current * {@link ImageView.ScaleType}. */ - float getMaximumScale(); - - /** - * Returns the current scale value - * - * @return float - current scale value - */ - float getScale(); + @Deprecated + float getMaxScale(); /** - * Return the current scale type in use by the ImageView. + * Use {@link #setMaximumScale(float maximumScale)} instead, this will be removed in future + * release + *

 

+ * Sets the maximum scale level. What this value represents depends on the current {@link + * ImageView.ScaleType}. * - * @return current ImageView.ScaleType + * @param maxScale maximum allowed scale preset */ - ImageView.ScaleType getScaleType(); + @Deprecated + void setMaxScale(float maxScale); /** - * Whether to allow the ImageView's parent to intercept the touch event when the photo is scroll - * to it's horizontal edge. - * - * @param allow whether to allow intercepting by parent element or not + * @return The current maximum scale level. What this value represents depends on the current + * {@link ImageView.ScaleType}. */ - void setAllowParentInterceptOnEdge(boolean allow); + float getMaximumScale(); /** - * Use {@link #setMinimumScale(float minimumScale)} instead, this will be removed in future - * release - *

 

- * Sets the minimum scale level. What this value represents depends on the current {@link + * Sets the maximum scale level. What this value represents depends on the current {@link * ImageView.ScaleType}. * - * @param minScale minimum allowed scale + * @param maximumScale maximum allowed scale preset */ - @Deprecated - void setMinScale(float minScale); + void setMaximumScale(float maximumScale); /** - * Sets the minimum scale level. What this value represents depends on the current {@link - * ImageView.ScaleType}. + * Returns the current scale value * - * @param minimumScale minimum allowed scale + * @return float - current scale value */ - void setMinimumScale(float minimumScale); + float getScale(); /** - * Use {@link #setMediumScale(float mediumScale)} instead, this will be removed in future - * release - *

 

- * Sets the middle scale level. What this value represents depends on the current {@link - * ImageView.ScaleType}. + * Changes the current scale to the specified value. * - * @param midScale medium scale preset + * @param scale - Value to scale to */ - @Deprecated - void setMidScale(float midScale); + void setScale(float scale); /** - * Sets the medium scale level. What this value represents depends on the current {@link ImageView.ScaleType}. + * Return the current scale type in use by the ImageView. * - * @param mediumScale medium scale preset + * @return current ImageView.ScaleType */ - void setMediumScale(float mediumScale); + ImageView.ScaleType getScaleType(); /** - * Use {@link #setMaximumScale(float maximumScale)} instead, this will be removed in future - * release - *

 

- * Sets the maximum scale level. What this value represents depends on the current {@link + * Controls how the image should be resized or moved to match the size of the ImageView. Any + * scaling or panning will happen within the confines of this {@link * ImageView.ScaleType}. * - * @param maxScale maximum allowed scale preset + * @param scaleType - The desired scaling mode. */ - @Deprecated - void setMaxScale(float maxScale); + void setScaleType(ImageView.ScaleType scaleType); /** - * Sets the maximum scale level. What this value represents depends on the current {@link - * ImageView.ScaleType}. + * Whether to allow the ImageView's parent to intercept the touch event when the photo is scroll + * to it's horizontal edge. * - * @param maximumScale maximum allowed scale preset + * @param allow whether to allow intercepting by parent element or not */ - void setMaximumScale(float maximumScale); + void setAllowParentInterceptOnEdge(boolean allow); /** * Allows to set all three scale levels at once, so you don't run into problem with setting @@ -221,14 +237,6 @@ public interface IPhotoView { */ void setOnMatrixChangeListener(PhotoViewAttacher.OnMatrixChangedListener listener); - /** - * Register a callback to be invoked when the Photo displayed by this View is tapped with a - * single tap. - * - * @param listener - Listener to be registered. - */ - void setOnPhotoTapListener(PhotoViewAttacher.OnPhotoTapListener listener); - /** * PhotoViewAttacher.OnPhotoTapListener reference should be stored in a variable instead, this * will be removed in future release. @@ -242,11 +250,12 @@ public interface IPhotoView { PhotoViewAttacher.OnPhotoTapListener getOnPhotoTapListener(); /** - * Register a callback to be invoked when the View is tapped with a single tap. + * Register a callback to be invoked when the Photo displayed by this View is tapped with a + * single tap. * * @param listener - Listener to be registered. */ - void setOnViewTapListener(PhotoViewAttacher.OnViewTapListener listener); + void setOnPhotoTapListener(PhotoViewAttacher.OnPhotoTapListener listener); /** * Enables rotation via PhotoView internal functions. @@ -274,11 +283,11 @@ public interface IPhotoView { PhotoViewAttacher.OnViewTapListener getOnViewTapListener(); /** - * Changes the current scale to the specified value. + * Register a callback to be invoked when the View is tapped with a single tap. * - * @param scale - Value to scale to + * @param listener - Listener to be registered. */ - void setScale(float scale); + void setOnViewTapListener(PhotoViewAttacher.OnViewTapListener listener); /** * Changes the current scale to the specified value. @@ -298,15 +307,6 @@ public interface IPhotoView { */ void setScale(float scale, float focalX, float focalY, boolean animate); - /** - * Controls how the image should be resized or moved to match the size of the ImageView. Any - * scaling or panning will happen within the confines of this {@link - * ImageView.ScaleType}. - * - * @param scaleType - The desired scaling mode. - */ - void setScaleType(ImageView.ScaleType scaleType); - /** * Allows you to enable/disable the zoom functionality on the ImageView. When disable the * ImageView reverts to using the FIT_CENTER matrix. diff --git a/library/src/main/java/uk/co/senab/photoview/PhotoView.java b/library/src/main/java/uk/co/senab/photoview/PhotoView.java index e224ab80..bb05bc2c 100755 --- a/library/src/main/java/uk/co/senab/photoview/PhotoView.java +++ b/library/src/main/java/uk/co/senab/photoview/PhotoView.java @@ -109,11 +109,22 @@ public float getMinScale() { return getMinimumScale(); } + @Override + @Deprecated + public void setMinScale(float minScale) { + setMinimumScale(minScale); + } + @Override public float getMinimumScale() { return mAttacher.getMinimumScale(); } + @Override + public void setMinimumScale(float minimumScale) { + mAttacher.setMinimumScale(minimumScale); + } + @Override @Deprecated public float getMidScale() { @@ -121,67 +132,70 @@ public float getMidScale() { } @Override - public float getMediumScale() { - return mAttacher.getMediumScale(); + @Deprecated + public void setMidScale(float midScale) { + setMediumScale(midScale); } @Override - @Deprecated - public float getMaxScale() { - return getMaximumScale(); + public float getMediumScale() { + return mAttacher.getMediumScale(); } @Override - public float getMaximumScale() { - return mAttacher.getMaximumScale(); + public void setMediumScale(float mediumScale) { + mAttacher.setMediumScale(mediumScale); } @Override - public float getScale() { - return mAttacher.getScale(); + @Deprecated + public float getMaxScale() { + return getMaximumScale(); } @Override - public ScaleType getScaleType() { - return mAttacher.getScaleType(); + @Deprecated + public void setMaxScale(float maxScale) { + setMaximumScale(maxScale); } @Override - public void setAllowParentInterceptOnEdge(boolean allow) { - mAttacher.setAllowParentInterceptOnEdge(allow); + public float getMaximumScale() { + return mAttacher.getMaximumScale(); } @Override - @Deprecated - public void setMinScale(float minScale) { - setMinimumScale(minScale); + public void setMaximumScale(float maximumScale) { + mAttacher.setMaximumScale(maximumScale); } @Override - public void setMinimumScale(float minimumScale) { - mAttacher.setMinimumScale(minimumScale); + public float getScale() { + return mAttacher.getScale(); } @Override - @Deprecated - public void setMidScale(float midScale) { - setMediumScale(midScale); + public void setScale(float scale) { + mAttacher.setScale(scale); } @Override - public void setMediumScale(float mediumScale) { - mAttacher.setMediumScale(mediumScale); + public ScaleType getScaleType() { + return mAttacher.getScaleType(); } @Override - @Deprecated - public void setMaxScale(float maxScale) { - setMaximumScale(maxScale); + public void setScaleType(ScaleType scaleType) { + if (null != mAttacher) { + mAttacher.setScaleType(scaleType); + } else { + mPendingScaleType = scaleType; + } } @Override - public void setMaximumScale(float maximumScale) { - mAttacher.setMaximumScale(maximumScale); + public void setAllowParentInterceptOnEdge(boolean allow) { + mAttacher.setAllowParentInterceptOnEdge(allow); } @Override @@ -224,11 +238,6 @@ public void setOnLongClickListener(OnLongClickListener l) { mAttacher.setOnLongClickListener(l); } - @Override - public void setOnPhotoTapListener(OnPhotoTapListener listener) { - mAttacher.setOnPhotoTapListener(listener); - } - @Override @Deprecated public OnPhotoTapListener getOnPhotoTapListener() { @@ -236,8 +245,8 @@ public OnPhotoTapListener getOnPhotoTapListener() { } @Override - public void setOnViewTapListener(OnViewTapListener listener) { - mAttacher.setOnViewTapListener(listener); + public void setOnPhotoTapListener(OnPhotoTapListener listener) { + mAttacher.setOnPhotoTapListener(listener); } @Override @@ -247,8 +256,8 @@ public OnViewTapListener getOnViewTapListener() { } @Override - public void setScale(float scale) { - mAttacher.setScale(scale); + public void setOnViewTapListener(OnViewTapListener listener) { + mAttacher.setOnViewTapListener(listener); } @Override @@ -261,15 +270,6 @@ public void setScale(float scale, float focalX, float focalY, boolean animate) { mAttacher.setScale(scale, focalX, focalY, animate); } - @Override - public void setScaleType(ScaleType scaleType) { - if (null != mAttacher) { - mAttacher.setScaleType(scaleType); - } else { - mPendingScaleType = scaleType; - } - } - @Override public void setZoomable(boolean zoomable) { mAttacher.setZoomable(zoomable); diff --git a/library/src/main/java/uk/co/senab/photoview/PhotoViewAttacher.java b/library/src/main/java/uk/co/senab/photoview/PhotoViewAttacher.java index 48809821..f96bd6a2 100644 --- a/library/src/main/java/uk/co/senab/photoview/PhotoViewAttacher.java +++ b/library/src/main/java/uk/co/senab/photoview/PhotoViewAttacher.java @@ -22,7 +22,7 @@ import android.graphics.Matrix.ScaleToFit; import android.graphics.RectF; import android.graphics.drawable.Drawable; -import android.support.v4.view.MotionEventCompat; +import androidx.core.view.MotionEventCompat; import android.util.Log; import android.view.GestureDetector; import android.view.MotionEvent; @@ -50,93 +50,32 @@ public class PhotoViewAttacher implements IPhotoView, View.OnTouchListener, OnGestureListener, ViewTreeObserver.OnGlobalLayoutListener { - private static final String LOG_TAG = "PhotoViewAttacher"; - - // let debug flag be dynamic, but still Proguard can be used to remove from - // release builds - private static final boolean DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG); - - private Interpolator mInterpolator = new AccelerateDecelerateInterpolator(); - int ZOOM_DURATION = DEFAULT_ZOOM_DURATION; - static final int EDGE_NONE = -1; static final int EDGE_LEFT = 0; static final int EDGE_RIGHT = 1; static final int EDGE_BOTH = 2; - + private static final String LOG_TAG = "PhotoViewAttacher"; + // let debug flag be dynamic, but still Proguard can be used to remove from + // release builds + private static final boolean DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG); static int SINGLE_TOUCH = 1; - + // These are set so we don't keep allocating them on the heap + private final Matrix mBaseMatrix = new Matrix(); + private final Matrix mDrawMatrix = new Matrix(); + private final Matrix mSuppMatrix = new Matrix(); + private final RectF mDisplayRect = new RectF(); + private final float[] mMatrixValues = new float[9]; + int ZOOM_DURATION = DEFAULT_ZOOM_DURATION; + private Interpolator mInterpolator = new AccelerateDecelerateInterpolator(); private float mMinScale = DEFAULT_MIN_SCALE; private float mMidScale = DEFAULT_MID_SCALE; private float mMaxScale = DEFAULT_MAX_SCALE; - private boolean mAllowParentInterceptOnEdge = true; private boolean mBlockParentIntercept = false; - - private static void checkZoomLevels(float minZoom, float midZoom, - float maxZoom) { - if (minZoom >= midZoom) { - throw new IllegalArgumentException( - "Minimum zoom has to be less than Medium zoom. Call setMinimumZoom() with a more appropriate value"); - } else if (midZoom >= maxZoom) { - throw new IllegalArgumentException( - "Medium zoom has to be less than Maximum zoom. Call setMaximumZoom() with a more appropriate value"); - } - } - - /** - * @return true if the ImageView exists, and it's Drawable exists - */ - private static boolean hasDrawable(ImageView imageView) { - return null != imageView && null != imageView.getDrawable(); - } - - /** - * @return true if the ScaleType is supported. - */ - private static boolean isSupportedScaleType(final ScaleType scaleType) { - if (null == scaleType) { - return false; - } - - switch (scaleType) { - case MATRIX: - throw new IllegalArgumentException(scaleType.name() - + " is not supported in PhotoView"); - - default: - return true; - } - } - - /** - * Set's the ImageView's ScaleType to Matrix. - */ - private static void setImageViewScaleTypeMatrix(ImageView imageView) { - /** - * PhotoView sets it's own ScaleType to Matrix, then diverts all calls - * setScaleType to this.setScaleType automatically. - */ - if (null != imageView && !(imageView instanceof IPhotoView)) { - if (!ScaleType.MATRIX.equals(imageView.getScaleType())) { - imageView.setScaleType(ScaleType.MATRIX); - } - } - } - private WeakReference mImageView; - // Gesture Detectors private GestureDetector mGestureDetector; private uk.co.senab.photoview.gestures.GestureDetector mScaleDragDetector; - - // These are set so we don't keep allocating them on the heap - private final Matrix mBaseMatrix = new Matrix(); - private final Matrix mDrawMatrix = new Matrix(); - private final Matrix mSuppMatrix = new Matrix(); - private final RectF mDisplayRect = new RectF(); - private final float[] mMatrixValues = new float[9]; - // Listeners private OnMatrixChangedListener mMatrixChangeListener; private OnPhotoTapListener mPhotoTapListener; @@ -144,12 +83,10 @@ private static void setImageViewScaleTypeMatrix(ImageView imageView) { private OnLongClickListener mLongClickListener; private OnScaleChangeListener mScaleChangeListener; private OnSingleFlingListener mSingleFlingListener; - private int mIvTop, mIvRight, mIvBottom, mIvLeft; private FlingRunnable mCurrentFlingRunnable; private int mScrollEdge = EDGE_BOTH; private float mBaseRotation; - private boolean mZoomEnabled; private ScaleType mScaleType = ScaleType.FIT_CENTER; @@ -214,6 +151,57 @@ public boolean onFling(MotionEvent e1, MotionEvent e2, setZoomable(zoomable); } + private static void checkZoomLevels(float minZoom, float midZoom, + float maxZoom) { + if (minZoom >= midZoom) { + throw new IllegalArgumentException( + "Minimum zoom has to be less than Medium zoom. Call setMinimumZoom() with a more appropriate value"); + } else if (midZoom >= maxZoom) { + throw new IllegalArgumentException( + "Medium zoom has to be less than Maximum zoom. Call setMaximumZoom() with a more appropriate value"); + } + } + + /** + * @return true if the ImageView exists, and it's Drawable exists + */ + private static boolean hasDrawable(ImageView imageView) { + return null != imageView && null != imageView.getDrawable(); + } + + /** + * @return true if the ScaleType is supported. + */ + private static boolean isSupportedScaleType(final ScaleType scaleType) { + if (null == scaleType) { + return false; + } + + switch (scaleType) { + case MATRIX: + throw new IllegalArgumentException(scaleType.name() + + " is not supported in PhotoView"); + + default: + return true; + } + } + + /** + * Set's the ImageView's ScaleType to Matrix. + */ + private static void setImageViewScaleTypeMatrix(ImageView imageView) { + /** + * PhotoView sets it's own ScaleType to Matrix, then diverts all calls + * setScaleType to this.setScaleType automatically. + */ + if (null != imageView && !(imageView instanceof IPhotoView)) { + if (!ScaleType.MATRIX.equals(imageView.getScaleType())) { + imageView.setScaleType(ScaleType.MATRIX); + } + } + } + @Override public void setOnDoubleTapListener(GestureDetector.OnDoubleTapListener newOnDoubleTapListener) { if (newOnDoubleTapListener != null) { @@ -357,53 +345,100 @@ public float getMinScale() { return getMinimumScale(); } + @Override + @Deprecated + public void setMinScale(float minScale) { + setMinimumScale(minScale); + } + @Override public float getMinimumScale() { return mMinScale; } + @Override + public void setMinimumScale(float minimumScale) { + checkZoomLevels(minimumScale, mMidScale, mMaxScale); + mMinScale = minimumScale; + } + @Override @Deprecated public float getMidScale() { return getMediumScale(); } + @Override + @Deprecated + public void setMidScale(float midScale) { + setMediumScale(midScale); + } + @Override public float getMediumScale() { return mMidScale; } + @Override + public void setMediumScale(float mediumScale) { + checkZoomLevels(mMinScale, mediumScale, mMaxScale); + mMidScale = mediumScale; + } + @Override @Deprecated public float getMaxScale() { return getMaximumScale(); } + @Override + @Deprecated + public void setMaxScale(float maxScale) { + setMaximumScale(maxScale); + } + @Override public float getMaximumScale() { return mMaxScale; } + @Override + public void setMaximumScale(float maximumScale) { + checkZoomLevels(mMinScale, mMidScale, maximumScale); + mMaxScale = maximumScale; + } + @Override public float getScale() { return (float) Math.sqrt((float) Math.pow(getValue(mSuppMatrix, Matrix.MSCALE_X), 2) + (float) Math.pow(getValue(mSuppMatrix, Matrix.MSKEW_Y), 2)); } + @Override + public void setScale(float scale) { + setScale(scale, false); + } + @Override public ScaleType getScaleType() { return mScaleType; } + @Override + public void setScaleType(ScaleType scaleType) { + if (isSupportedScaleType(scaleType) && scaleType != mScaleType) { + mScaleType = scaleType; + + // Finally update + update(); + } + } + @Override public void onDrag(float dx, float dy) { if (mScaleDragDetector.isScaling()) { return; // Do not drag if we are already scaling } - if (DEBUG) { - Logger.d(String.format("onDrag: dx: %.2f. dy: %.2f", dx, dy)); - } - ImageView imageView = getImageView(); mSuppMatrix.postTranslate(dx, dy); checkAndDisplayMatrix(); @@ -436,10 +471,6 @@ public void onDrag(float dx, float dy) { @Override public void onFling(float startX, float startY, float velocityX, float velocityY) { - if (DEBUG) { - Logger.d("onFling. sX: " + startX + " sY: " + startY + " Vx: " - + velocityX + " Vy: " + velocityY); - } ImageView imageView = getImageView(); mCurrentFlingRunnable = new FlingRunnable(imageView.getContext()); mCurrentFlingRunnable.fling(getImageViewWidth(imageView), @@ -484,11 +515,6 @@ public void onGlobalLayout() { @Override public void onScale(float scaleFactor, float focusX, float focusY) { - if (DEBUG) { - Logger.d(String.format("onScale: scale: %.2f. fX: %.2f. fY: %.2f", - scaleFactor, focusX, focusY)); - } - if ((getScale() < mMaxScale || scaleFactor < 1f) && (getScale() > mMinScale || scaleFactor > 1f)) { if (null != mScaleChangeListener) { mScaleChangeListener.onScaleChange(scaleFactor, focusX, focusY); @@ -563,42 +589,6 @@ public void setAllowParentInterceptOnEdge(boolean allow) { mAllowParentInterceptOnEdge = allow; } - @Override - @Deprecated - public void setMinScale(float minScale) { - setMinimumScale(minScale); - } - - @Override - public void setMinimumScale(float minimumScale) { - checkZoomLevels(minimumScale, mMidScale, mMaxScale); - mMinScale = minimumScale; - } - - @Override - @Deprecated - public void setMidScale(float midScale) { - setMediumScale(midScale); - } - - @Override - public void setMediumScale(float mediumScale) { - checkZoomLevels(mMinScale, mediumScale, mMaxScale); - mMidScale = mediumScale; - } - - @Override - @Deprecated - public void setMaxScale(float maxScale) { - setMaximumScale(maxScale); - } - - @Override - public void setMaximumScale(float maximumScale) { - checkZoomLevels(mMinScale, mMidScale, maximumScale); - mMaxScale = maximumScale; - } - @Override public void setScaleLevels(float minimumScale, float mediumScale, float maximumScale) { checkZoomLevels(minimumScale, mediumScale, maximumScale); @@ -617,11 +607,6 @@ public void setOnMatrixChangeListener(OnMatrixChangedListener listener) { mMatrixChangeListener = listener; } - @Override - public void setOnPhotoTapListener(OnPhotoTapListener listener) { - mPhotoTapListener = listener; - } - @Override @Deprecated public OnPhotoTapListener getOnPhotoTapListener() { @@ -629,8 +614,8 @@ public OnPhotoTapListener getOnPhotoTapListener() { } @Override - public void setOnViewTapListener(OnViewTapListener listener) { - mViewTapListener = listener; + public void setOnPhotoTapListener(OnPhotoTapListener listener) { + mPhotoTapListener = listener; } @Override @@ -640,8 +625,8 @@ public OnViewTapListener getOnViewTapListener() { } @Override - public void setScale(float scale) { - setScale(scale, false); + public void setOnViewTapListener(OnViewTapListener listener) { + mViewTapListener = listener; } @Override @@ -680,22 +665,13 @@ public void setScale(float scale, float focalX, float focalY, /** * Set the zoom interpolator + * * @param interpolator the zoom interpolator */ public void setZoomInterpolator(Interpolator interpolator) { mInterpolator = interpolator; } - @Override - public void setScaleType(ScaleType scaleType) { - if (isSupportedScaleType(scaleType) && scaleType != mScaleType) { - mScaleType = scaleType; - - // Finally update - update(); - } - } - @Override public void setZoomable(boolean zoomable) { mZoomEnabled = zoomable; @@ -730,6 +706,7 @@ public Matrix getDisplayMatrix() { /** * Like {@link #getDisplayMatrix()}, but allows the user to provide a matrix to copy the values into to reduce object allocation + * * @param matrix target matrix to copy to */ @Override @@ -781,7 +758,7 @@ private void checkImageViewScaleType() { if (null != imageView && !(imageView instanceof IPhotoView)) { if (!ScaleType.MATRIX.equals(imageView.getScaleType())) { throw new IllegalStateException( - "The ImageView's ScaleType has been changed since attaching a PhotoViewAttacher. You should call setScaleType on the PhotoViewAttacher instead of on the ImageView" ); + "The ImageView's ScaleType has been changed since attaching a PhotoViewAttacher. You should call setScaleType on the PhotoViewAttacher instead of on the ImageView"); } } } @@ -1062,7 +1039,7 @@ public interface OnPhotoTapListener { /** * A simple callback where out of photo happened; - * */ + */ void onOutsidePhotoTap(); } @@ -1157,9 +1134,6 @@ public FlingRunnable(Context context) { } public void cancelFling() { - if (DEBUG) { - Logger.d("Cancel Fling"); - } mScroller.forceFinished(true); } @@ -1191,11 +1165,6 @@ public void fling(int viewWidth, int viewHeight, int velocityX, mCurrentX = startX; mCurrentY = startY; - if (DEBUG) { - Logger.d("fling. StartX:" + startX + " StartY:" + startY - + " MaxX:" + maxX + " MaxY:" + maxY); - } - // If we actually can move, fling the scroller if (startX != maxX || startY != maxY) { mScroller.fling(startX, startY, velocityX, velocityY, minX, @@ -1215,12 +1184,6 @@ public void run() { final int newX = mScroller.getCurrX(); final int newY = mScroller.getCurrY(); - if (DEBUG) { - Logger.d("fling run(). CurrentX:" + mCurrentX + " CurrentY:" - + mCurrentY + " NewX:" + newX + " NewY:" - + newY); - } - mSuppMatrix.postTranslate(mCurrentX - newX, mCurrentY - newY); setImageViewMatrix(getDrawMatrix()); diff --git a/library/src/main/java/uk/co/senab/photoview/gestures/CupcakeGestureDetector.java b/library/src/main/java/uk/co/senab/photoview/gestures/CupcakeGestureDetector.java index b87c5b2e..a526bb77 100755 --- a/library/src/main/java/uk/co/senab/photoview/gestures/CupcakeGestureDetector.java +++ b/library/src/main/java/uk/co/senab/photoview/gestures/CupcakeGestureDetector.java @@ -24,17 +24,14 @@ public class CupcakeGestureDetector implements GestureDetector { - protected OnGestureListener mListener; private static final String LOG_TAG = "CupcakeGestureDetector"; - float mLastTouchX; - float mLastTouchY; final float mTouchSlop; final float mMinimumVelocity; - - @Override - public void setOnGestureListener(OnGestureListener listener) { - this.mListener = listener; - } + protected OnGestureListener mListener; + float mLastTouchX; + float mLastTouchY; + private VelocityTracker mVelocityTracker; + private boolean mIsDragging; public CupcakeGestureDetector(Context context) { final ViewConfiguration configuration = ViewConfiguration @@ -43,8 +40,10 @@ public CupcakeGestureDetector(Context context) { mTouchSlop = configuration.getScaledTouchSlop(); } - private VelocityTracker mVelocityTracker; - private boolean mIsDragging; + @Override + public void setOnGestureListener(OnGestureListener listener) { + this.mListener = listener; + } float getActiveX(MotionEvent ev) { return ev.getX(); diff --git a/library/src/main/jniLibs/arm64-v8a/libucrop.so b/library/src/main/jniLibs/arm64-v8a/libucrop.so deleted file mode 100755 index e3911d6c..00000000 Binary files a/library/src/main/jniLibs/arm64-v8a/libucrop.so and /dev/null differ diff --git a/library/src/main/jniLibs/armeabi-v7a/libucrop.so b/library/src/main/jniLibs/armeabi-v7a/libucrop.so deleted file mode 100755 index b6172412..00000000 Binary files a/library/src/main/jniLibs/armeabi-v7a/libucrop.so and /dev/null differ diff --git a/library/src/main/jniLibs/armeabi/libucrop.so b/library/src/main/jniLibs/armeabi/libucrop.so deleted file mode 100755 index 6be5f557..00000000 Binary files a/library/src/main/jniLibs/armeabi/libucrop.so and /dev/null differ diff --git a/library/src/main/jniLibs/x86/libucrop.so b/library/src/main/jniLibs/x86/libucrop.so deleted file mode 100755 index 5de62c1e..00000000 Binary files a/library/src/main/jniLibs/x86/libucrop.so and /dev/null differ diff --git a/library/src/main/jniLibs/x86_64/libucrop.so b/library/src/main/jniLibs/x86_64/libucrop.so deleted file mode 100755 index 53bb591a..00000000 Binary files a/library/src/main/jniLibs/x86_64/libucrop.so and /dev/null differ 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/color/gallery_text_color_selector.xml b/library/src/main/res/color/gallery_text_color_selector.xml index 64e6f4fe..19cf9ac8 100644 --- a/library/src/main/res/color/gallery_text_color_selector.xml +++ b/library/src/main/res/color/gallery_text_color_selector.xml @@ -1,6 +1,6 @@ - - + + \ No newline at end of file diff --git a/library/src/main/res/color/gallery_ucrop_scale_text_view_selector.xml b/library/src/main/res/color/gallery_ucrop_scale_text_view_selector.xml deleted file mode 100755 index 689c3137..00000000 --- a/library/src/main/res/color/gallery_ucrop_scale_text_view_selector.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_cross.png b/library/src/main/res/drawable-hdpi/gallery_ic_cross.png old mode 100755 new mode 100644 similarity index 100% rename from library/src/main/res/drawable-hdpi/gallery_ucrop_ic_cross.png rename to library/src/main/res/drawable-hdpi/gallery_ic_cross.png 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 218d5609..00000000 Binary files a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_angle.png and /dev/null differ diff --git a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_crop.png b/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_crop.png deleted file mode 100755 index a12fdfc7..00000000 Binary files a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_crop.png and /dev/null differ 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 70472dd9..00000000 Binary files a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_done.png and /dev/null differ 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 d1b1cddb..00000000 Binary files a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_next.png and /dev/null differ diff --git a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_reset.png b/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_reset.png deleted file mode 100755 index 2b6692bb..00000000 Binary files a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_reset.png and /dev/null differ diff --git a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_rotate.png b/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_rotate.png deleted file mode 100755 index ba20cf35..00000000 Binary files a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_rotate.png and /dev/null differ diff --git a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_scale.png b/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_scale.png deleted file mode 100755 index 0be967cd..00000000 Binary files a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_scale.png and /dev/null differ diff --git a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_cross.png b/library/src/main/res/drawable-ldpi/gallery_ic_cross.png old mode 100755 new mode 100644 similarity index 100% rename from library/src/main/res/drawable-ldpi/gallery_ucrop_ic_cross.png rename to library/src/main/res/drawable-ldpi/gallery_ic_cross.png diff --git a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_angle.png b/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_angle.png deleted file mode 100755 index 41af9796..00000000 Binary files a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_angle.png and /dev/null differ diff --git a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_crop.png b/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_crop.png deleted file mode 100755 index 19daec37..00000000 Binary files a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_crop.png and /dev/null differ 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 9e48718a..00000000 Binary files a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_done.png and /dev/null differ diff --git a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_next.png b/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_next.png deleted file mode 100755 index 732e9a78..00000000 Binary files a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_next.png and /dev/null differ diff --git a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_reset.png b/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_reset.png deleted file mode 100755 index dfdb5bc9..00000000 Binary files a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_reset.png and /dev/null differ 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 d812eada..00000000 Binary files a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_rotate.png and /dev/null differ diff --git a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_scale.png b/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_scale.png deleted file mode 100755 index 2522ac7d..00000000 Binary files a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_scale.png and /dev/null differ diff --git a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_cross.png b/library/src/main/res/drawable-mdpi/gallery_ic_cross.png old mode 100755 new mode 100644 similarity index 100% rename from library/src/main/res/drawable-mdpi/gallery_ucrop_ic_cross.png rename to library/src/main/res/drawable-mdpi/gallery_ic_cross.png diff --git a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_angle.png b/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_angle.png deleted file mode 100755 index 9945b062..00000000 Binary files a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_angle.png and /dev/null differ 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 36e4f362..00000000 Binary files a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_crop.png and /dev/null differ 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 ddf1cd96..00000000 Binary files a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_done.png and /dev/null differ 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 8f972bb0..00000000 Binary files a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_next.png and /dev/null differ diff --git a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_reset.png b/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_reset.png deleted file mode 100755 index 5431cd34..00000000 Binary files a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_reset.png and /dev/null differ diff --git a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_rotate.png b/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_rotate.png deleted file mode 100755 index f7890066..00000000 Binary files a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_rotate.png and /dev/null differ 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 ac363b77..00000000 Binary files a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_scale.png and /dev/null differ diff --git a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_cross.png b/library/src/main/res/drawable-xhdpi/gallery_ic_cross.png old mode 100755 new mode 100644 similarity index 100% rename from library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_cross.png rename to library/src/main/res/drawable-xhdpi/gallery_ic_cross.png diff --git a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_angle.png b/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_angle.png deleted file mode 100755 index 27d13187..00000000 Binary files a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_angle.png and /dev/null differ diff --git a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_crop.png b/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_crop.png deleted file mode 100755 index f18a41c3..00000000 Binary files a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_crop.png and /dev/null differ 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 e588817f..00000000 Binary files a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_done.png and /dev/null differ 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 6cd8e294..00000000 Binary files a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_next.png and /dev/null differ 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 15f8a7b2..00000000 Binary files a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_reset.png and /dev/null differ 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 d10f0c99..00000000 Binary files a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_rotate.png and /dev/null differ 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 cdb82257..00000000 Binary files a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_scale.png and /dev/null differ diff --git a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_cross.png b/library/src/main/res/drawable-xxhdpi/gallery_ic_cross.png old mode 100755 new mode 100644 similarity index 100% rename from library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_cross.png rename to library/src/main/res/drawable-xxhdpi/gallery_ic_cross.png diff --git a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_angle.png b/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_angle.png deleted file mode 100755 index 30d941d3..00000000 Binary files a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_angle.png and /dev/null differ 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 7decf1a3..00000000 Binary files a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_crop.png and /dev/null differ diff --git a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_done.png b/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_done.png deleted file mode 100755 index 9e84e9ad..00000000 Binary files a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_done.png and /dev/null differ diff --git a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_next.png b/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_next.png deleted file mode 100755 index d6f68f37..00000000 Binary files a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_next.png and /dev/null differ diff --git a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_reset.png b/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_reset.png deleted file mode 100755 index 52870ba0..00000000 Binary files a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_reset.png and /dev/null differ diff --git a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_rotate.png b/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_rotate.png deleted file mode 100755 index 91b1c8ed..00000000 Binary files a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_rotate.png and /dev/null differ diff --git a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_scale.png b/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_scale.png deleted file mode 100755 index 158335cc..00000000 Binary files a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_scale.png and /dev/null differ 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_cross.png b/library/src/main/res/drawable-xxxhdpi/gallery_ic_cross.png old mode 100755 new mode 100644 similarity index 100% rename from library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_cross.png rename to library/src/main/res/drawable-xxxhdpi/gallery_ic_cross.png 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 68eb67e0..00000000 Binary files a/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_angle.png and /dev/null differ 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 8dfce883..00000000 Binary files a/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_crop.png and /dev/null differ 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 fe6352d8..00000000 Binary files a/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_done.png and /dev/null differ diff --git a/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_next.png b/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_next.png deleted file mode 100755 index 9f645340..00000000 Binary files a/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_next.png and /dev/null differ diff --git a/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_reset.png b/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_reset.png deleted file mode 100755 index 75a92c0d..00000000 Binary files a/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_reset.png and /dev/null differ diff --git a/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_rotate.png b/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_rotate.png deleted file mode 100755 index 7525f926..00000000 Binary files a/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_rotate.png and /dev/null differ 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 21fc505b..00000000 Binary files a/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_scale.png and /dev/null differ 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_checkbox_selector.xml b/library/src/main/res/drawable/gallery_checkbox_selector.xml deleted file mode 100644 index 2d864820..00000000 --- a/library/src/main/res/drawable/gallery_checkbox_selector.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file 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..5353d05a 100644 --- a/library/src/main/res/layout/gallery_activity_media.xml +++ b/library/src/main/res/layout/gallery_activity_media.xml @@ -4,7 +4,7 @@ android:layout_height="match_parent" android:orientation="vertical"> - + 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_adapter_media_grid_item.xml b/library/src/main/res/layout/gallery_adapter_media_grid_item.xml index dedb002b..c2e7d2bc 100644 --- a/library/src/main/res/layout/gallery_adapter_media_grid_item.xml +++ b/library/src/main/res/layout/gallery_adapter_media_grid_item.xml @@ -29,11 +29,11 @@ android:layout_height="match_parent" android:scaleType="centerCrop"/> - + 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:background="@color/gallery_bucket_list_item_normal_color" /> + android:orientation="vertical" /> - + android:textColor="#FFFFFF" + 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..4f1bd072 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" /> - + + diff --git a/library/src/main/res/layout/gallery_item_media_grid.xml b/library/src/main/res/layout/gallery_item_media_grid.xml new file mode 100644 index 00000000..f2983d28 --- /dev/null +++ b/library/src/main/res/layout/gallery_item_media_grid.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/library/src/main/res/layout/gallery_item_media_grid_fresco.xml b/library/src/main/res/layout/gallery_item_media_grid_fresco.xml new file mode 100644 index 00000000..20fcf973 --- /dev/null +++ b/library/src/main/res/layout/gallery_item_media_grid_fresco.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + \ 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/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 new file mode 100644 index 00000000..399e37da --- /dev/null +++ b/library/src/main/res/values-en/gallery_strings.xml @@ -0,0 +1,25 @@ + + 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 + >App request to Camera + Absolutely empty + The device has no camera + Camera not available + preview + All pictures + All video + Photograph + Selected + pictures + cut + record video + 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 92be0ade..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请求拍照权限,否则无法拍照 空空如也 该设备无摄像头 相机不可用 @@ -17,4 +18,8 @@ 所有图片 所有视频 拍摄照片 + 选中 + + 裁剪 + 录制视频 diff --git a/library/src/main/res/values/gallery_styles.xml b/library/src/main/res/values/gallery_styles.xml new file mode 100644 index 00000000..249fd4e6 --- /dev/null +++ b/library/src/main/res/values/gallery_styles.xml @@ -0,0 +1,5 @@ + + + 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/library/src/test/java/cn/finalteam/rxgalleryfinal/ExampleUnitTest.java b/library/src/test/java/cn/finalteam/rxgalleryfinal/ExampleUnitTest.java deleted file mode 100644 index 323d5563..00000000 --- a/library/src/test/java/cn/finalteam/rxgalleryfinal/ExampleUnitTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.finalteam.rxgalleryfinal; - -import org.junit.Test; - -import java.text.SimpleDateFormat; -import java.util.Date; - -/** - * To work on unit tests, switch the Test Artifact in the Build Variants view. - */ -public class ExampleUnitTest { - @Test - public void addition_isCorrect() throws Exception { - SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); - System.out.println("====" + format.format(new Date())); - } -} \ No newline at end of file diff --git a/library/src/test/java/cn/finalteam/rxgalleryfinal/SimpleTest.java b/library/src/test/java/cn/finalteam/rxgalleryfinal/SimpleTest.java deleted file mode 100644 index ed97fa88..00000000 --- a/library/src/test/java/cn/finalteam/rxgalleryfinal/SimpleTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.finalteam.rxgalleryfinal; - - -import android.text.format.DateFormat; - -import org.junit.Test; - -import java.util.Date; - -/** - * Desction: - * Author:pengjianbo - * Date:16/6/3 上午10:30 - */ -public class SimpleTest { - - @Test - public void testDateFormat(){ - System.out.println("====" + DateFormat.format("yyyyMMddHHmmss", new Date())); - } - -} diff --git a/rxgalleryfinal-sample.apk b/rxgalleryfinal-sample.apk deleted file mode 100644 index e627ef92..00000000 Binary files a/rxgalleryfinal-sample.apk and /dev/null differ diff --git a/sample/build.gradle b/sample/build.gradle index cdcfdff9..a3f46b1a 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -1,15 +1,14 @@ apply plugin: 'com.android.application' -apply plugin: 'me.tatarka.retrolambda' apply plugin: 'com.getkeepsafe.dexcount' android { - compileSdkVersion 24 - buildToolsVersion '24.0.1' + compileSdkVersion 30 + buildToolsVersion '30.0.3' defaultConfig { applicationId "cn.finalteam.rxgalleryfinal.sample" - minSdkVersion 14 - targetSdkVersion 24 + minSdkVersion 16 + targetSdkVersion 30 versionCode 1 versionName "1.0" } @@ -24,23 +23,25 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } - compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } - lintOptions { abortOnError false } } dependencies { - compile fileTree(include: ['*.jar'], dir: 'libs') - testCompile 'junit:junit:4.12' - compile 'com.squareup.picasso:picasso:2.5.2' - compile 'com.facebook.fresco:fresco:0.12.0' - compile 'com.github.bumptech.glide:glide:3.7.0' - compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5' - compile project(':library') + implementation fileTree(include: ['*.jar'], dir: 'libs') + testImplementation 'junit:junit:4.12' + implementation 'com.squareup.picasso:picasso:2.5.2' + implementation 'com.facebook.fresco:fresco:1.3.0' + implementation 'com.facebook.fresco:animated-gif:1.3.0' + implementation 'com.github.bumptech.glide:glide:3.7.0' + implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.5' + debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.5.1' + releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1' + testImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1' + implementation project(':library') } diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml index cddba38e..e6792731 100644 --- a/sample/src/main/AndroidManifest.xml +++ b/sample/src/main/AndroidManifest.xml @@ -2,21 +2,24 @@ - - + - + + - + android:requestLegacyExternalStorage="true" + android:theme="@style/Theme_Light"> + + @@ -24,15 +27,15 @@ - + android:theme="@style/Theme_Light.Test" /> + android:screenOrientation="fullSensor" /> + \ No newline at end of file diff --git a/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/IApplication.java b/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/IApplication.java index 5455ffd7..48e9dc76 100644 --- a/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/IApplication.java +++ b/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/IApplication.java @@ -2,9 +2,18 @@ import android.app.Application; +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.squareup.leakcanary.LeakCanary; + +import cn.finalteam.rxgalleryfinal.utils.ModelUtils; + /** * Desction: - * Author:pengjianbo + * Author:pengjianbo Dujinyang * Date:16/5/16 上午9:17 */ public class IApplication extends Application { @@ -12,5 +21,20 @@ public class IApplication extends Application { @Override public void onCreate() { super.onCreate(); + //打开日志 + ModelUtils.setDebugModel(true); + Fresco.initialize(this); + 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()); + + if (LeakCanary.isInAnalyzerProcess(this)) { + return; + } + LeakCanary.install(this); } } 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..93d26789 100644 --- a/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/MainActivity.java +++ b/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/MainActivity.java @@ -1,86 +1,229 @@ package cn.finalteam.rxgalleryfinal.sample; +import android.content.Intent; import android.os.Bundle; -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 androidx.appcompat.app.AppCompatActivity; + +import java.util.List; import cn.finalteam.rxgalleryfinal.RxGalleryFinal; +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 { +public class MainActivity extends AppCompatActivity implements View.OnClickListener { - RadioButton mRbRadio,mRbMuti; - Button mBtnOpen; + RadioButton mRbRadioIMG, mRbMutiIMG, mRbOpenC, mRbRadioVD, mRbMutiVD; @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() - .imageLoader(ImageLoaderType.GLIDE) - .subscribe(new RxBusResultSubscriber() { + findViewById(R.id.btn_image_loader).setOnClickListener(this); + + findViewById(R.id.btn_open_img).setOnClickListener(this); + findViewById(R.id.btn_open_vd).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); + //多选事件的回调 + 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() - .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(); } - }) - .openGallery(); - } - }); + }); + //裁剪图片的回调 + RxGalleryListener + .getInstance() + .setRadioImageCheckedListener( + new IRadioImageCheckedListener() { + @Override + public void cropAfter(Object t) { + Toast.makeText(getBaseContext(), t.toString(), Toast.LENGTH_SHORT).show(); + } + + @Override + public boolean isActivityFinish() { + + return true; + } + }); + + } + + @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_img: + openImageSelect(); + break; + case R.id.btn_open_vd: + openVideoSelect(); + break; + + } } - 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 openVideoSelect() { + if (mRbRadioVD.isChecked()) { + openVideoSelectRadioMethod(); + } else if (mRbMutiVD.isChecked()) { + openVideoSelectMultiMethod(0); + } } - private void initFresco() { - Fresco.initialize(this); + /** + * 图片 + * 单选,多选, 直接打开相机 + */ + private void openImageSelect() { + + if (mRbRadioIMG.isChecked()) { + RxGalleryFinal + .with(MainActivity.this) + .image() + .radio() + .crop() + .imageLoader(ImageLoaderType.GLIDE) + .subscribe(new RxBusResultDisposable() { + @Override + protected void onEvent(ImageRadioResultEvent imageRadioResultEvent) throws Exception { + Logger.i("只要选择图片就会触发"); + } + }) + .openGallery(); + } else if (mRbMutiIMG.isChecked()) { + RxGalleryFinal + .with(MainActivity.this) + .image() + .multiple() + .maxSize(9) + .imageLoader(ImageLoaderType.GLIDE) + .subscribe(new RxBusResultDisposable() { + @Override + protected void onEvent(ImageMultipleResultEvent imageMultipleResultEvent) throws Exception { + Logger.i("多选图片的回调"); + } + }) + .openGallery(); + } else { + //if (PermissionCheckUtils.checkCameraPermission(this, "", MediaActivity.REQUEST_CAMERA_ACCESS_PERMISSION) + // && PermissionCheckUtils.checkWriteExternalPermission(this, "", MediaActivity.REQUEST_STORAGE_WRITE_ACCESS_PERMISSION) + // && PermissionCheckUtils.checkReadExternalPermission(this, "", MediaActivity.REQUEST_STORAGE_READ_ACCESS_PERMISSION)) { + // RxGalleryFinalApi.openZKCamera(MainActivity.this); + // } + } + } + + private List list = null; + + /** + * 视频多选回调 + */ + private void openVideoSelectMultiMethod(int type) { + RxGalleryFinal + .with(MainActivity.this) + .video() + .radio() + .imageLoader(ImageLoaderType.GLIDE) + .subscribe(new RxBusResultDisposable() { + @Override + protected void onEvent(ImageRadioResultEvent imageRadioResultEvent) throws Exception { + Logger.i("只要选择图片就会触发"); + } + }) + .openGallery(); } + /** + * 视频单选回调 + */ + private void openVideoSelectRadioMethod() { + RxGalleryFinal + .with(MainActivity.this) + .video() + .radio() + .imageLoader(ImageLoaderType.GLIDE) + .subscribe(new RxBusResultDisposable() { + @Override + protected void onEvent(ImageRadioResultEvent imageRadioResultEvent) throws Exception { + Logger.i("只要选择图片就会触发"); + } + }) + .openGallery(); + } + + /** + * OPEN 图片多选实现方法 + *

+ * 默认使用 第三个 ,如果运行sample,可自行改变Type,运行Demo查看效果 + */ + private void openImageSelectMultiMethod(int type) { + switch (type) { + case 0: + + break; + case 1: + //使用自定义的参数 + + break; + case 2: -} + break; + } + + } + + /** + * OPEN 图片单选实现方法 + *

+ * 默认使用 第三个 ,如果运行sample,可自行改变Type,运行Demo查看效果 + */ + private void openImageSelectRadioMethod(int type) { + + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + SimpleRxGalleryFinal.get().onActivityResult(requestCode, resultCode, data); + } +} \ 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..69775a50 --- /dev/null +++ b/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/SimpleRxGalleryFinal.java @@ -0,0 +1,153 @@ +package cn.finalteam.rxgalleryfinal.sample; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Environment; +import android.provider.MediaStore; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; + +import com.yalantis.ucrop.UCrop; + +import java.io.File; +import java.io.FileNotFoundException; + +import cn.finalteam.rxgalleryfinal.utils.FileUtils; + +/** + * 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 = FileUtils.fromFile(listener.getSimpleActivity(),getDiskCacheDir()); + intent.putExtra(MediaStore.EXTRA_OUTPUT, imagePath); + listener + .getSimpleActivity() + .startActivityForResult(intent, TYPE_CAMERA); + } + + public void onActivityResult(int requestCode, int resultCode, Intent data) { + switch (resultCode) { + case Activity.RESULT_CANCELED: + if(listener!=null){ + 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 + AppCompatActivity 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..472f0a68 --- /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 androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.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/layout/activity_imageloader.xml b/sample/src/main/res/layout/activity_imageloader.xml new file mode 100644 index 00000000..2910ec38 --- /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..69faf21f 100644 --- a/sample/src/main/res/layout/activity_main.xml +++ b/sample/src/main/res/layout/activity_main.xml @@ -3,38 +3,122 @@ 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"> + + + + + + android:checked="true" + android:text="单选" /> + + + + android:text="打开摄像头" /> +