一款针对 android 平台下的图片选择器,支持从相册或拍照选择图片或视频、音频,支持动态权限获取、裁剪(单图 or 多图裁剪)、压缩、主题自定义配置等功能、适配 android 6.0+系统的开源图片选择框架。
项目会一直维护(有 bug 修复完成,一般周末会更新),有 bug 请描述清楚,并请 Issues 会第一时间修复,Android 开发 QQ 交流群619458861,个人 QQ [email protected] 希望用得着的朋友点个 star。
PictureSelector 2.0 无裁剪功能版
我的博客地址
-功能特点
-集成方式
-常见错误
-功能配置
-缓存清除
-主题配置
-常用功能
-结果回调
-更新日志
-混淆配置
-兼容性测试
-演示效果
**那些遇到拍照闪退问题的同学,请记得看清下面适配 6.0 的配置~**
重要的事情说三遍记得添加权限
**注:适配 android6.0 以上拍照问题,请在 AndroidManifest.xml 中添加标签**
方式一 compile 引入
dependencies {
compile 'com.github.LuckSiege.PictureSelector:picture_library:v2.1.1'
}
项目根目录 build.gradle 加入
allprojects {
repositories {
jcenter()
maven { url 'https://jitpack.io' }
}
}
方式二 maven 引入
step 1.
jitpack.io
https://jitpack.io
step 2.
com.github.LuckSiege.PictureSelector
picture_library
v2.1.1
问题一:
rxjava 冲突:在 app build.gradle 下添加
packagingOptions {
exclude 'META-INF/rxjava.properties'
}
问题二:
java.lang.NullPointerException:
Attempt to invoke virtual method 'android.content.res.XmlResourceParser
android.content.pm.ProviderInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)'
on a null object reference
application 下添加如下节点:
注意:如已添加其他 sdk 或项目中已使用过 provider 节点,
[请参考我的博客](http://blog.csdn.net/luck_mw/article/details/54970105)的解决方案
问题三:
PhotoView 库冲突,可以删除自己项目中引用的,Picture_library 中已经引用过
com.github.chrisbanes.photoview:library:1.2.4
问题四:
经测试在小米部分低端机中,Fragment 调用 PictureSelector 2.0 拍照有时内存不足会暂时回收 activity,
导致其 fragment 会重新创建 建议在 fragment 所依赖的 activity 加上如下代码:
if (savedInstanceState == null) {
// 添加显示第一个 fragment
fragment = new PhotoFragment();
getSupportFragmentManager().beginTransaction().add(R.id.tab_content, fragment,
PictureConfig.FC_TAG).show(fragment)
.commit();
} else {
fragment = (PhotoFragment) getSupportFragmentManager()
.findFragmentByTag(PictureConfig.FC_TAG);
}
这里就是如果是被回收时,则不重新创建 通过 tag 取出 fragment 的实例。
问题五:
glide 冲突
由于 PictureSelector 2.0 引入的是最新的 glide 4.0.0,所以将项目中老版本的 glide 删除,并且将报错代码换成如下写法:
RequestOptions options = new RequestOptions();
options.placeholder(R.drawable.image);
Glide.with(context).load(url).apply(options).into(imageView);
// 进入相册 以下是例子:用不到的 api 可以不写
PictureSelector.create(MainActivity.this)
.openGallery()//全部.PictureMimeType.ofAll()、图片.ofImage()、视频.ofVideo()
.theme()//主题样式(不设置为默认样式) 也可参考 demo values/styles 下 例如:R.style.picture.white.style
.maxSelectNum()// 最大图片选择数量 int
.minSelectNum()// 最小选择数量 int
.imageSpanCount(4)// 每行显示个数 int
.selectionMode()// 多选 or 单选 PictureConfig.MULTIPLE or PictureConfig.SINGLE
.previewImage()// 是否可预览图片 true or false
.previewVideo()// 是否可预览视频 true or false
.enablePreviewAudio() // 是否可播放音频 true or false
.compressGrade()// luban 压缩档次,默认 3 档 Luban.THIRD_GEAR、Luban.FIRST_GEAR、Luban.CUSTOM_GEAR
.isCamera()// 是否显示拍照按钮 true or false
.isZoomAnim(true)// 图片列表点击 缩放效果 默认 true
.sizeMultiplier(0.5f)// glide 加载图片大小 0~1 之间 如设置 .glideOverride()无效
.setOutputCameraPath("/CustomPath")// 自定义拍照保存路径,可不填
.enableCrop()// 是否裁剪 true or false
.compress()// 是否压缩 true or false
.compressMode()//系统自带 or 鲁班压缩 PictureConfig.SYSTEM_COMPRESS_MODE or LUBAN_COMPRESS_MODE
.glideOverride()// int glide 加载宽高,越小图片列表越流畅,但会影响列表图片浏览的清晰度
.withAspectRatio()// int 裁剪比例 如 16:9 3:2 3:4 1:1 可自定义
.hideBottomControls()// 是否显示 uCrop 工具栏,默认不显示 true or false
.isGif()// 是否显示 gif 图片 true or false
.freeStyleCropEnabled()// 裁剪框是否可拖拽 true or false
.circleDimmedLayer()// 是否圆形裁剪 true or false
.showCropFrame()// 是否显示裁剪矩形边框 圆形裁剪时建议设为 false true or false
.showCropGrid()// 是否显示裁剪矩形网格 圆形裁剪时建议设为 false true or false
.openClickSound()// 是否开启点击声音 true or false
.selectionMedia()// 是否传入已选图片 List list
.previewEggs()// 预览图片时 是否增强左右滑动图片体验(图片滑动一半即可看到上一张是否选中) true or false
.cropCompressQuality()// 裁剪压缩质量 默认 90 int
.compressMaxKB()//压缩最大值 kb compressGrade()为 Luban.CUSTOM_GEAR 有效 int
.compressWH() // 压缩宽高比 compressGrade()为 Luban.CUSTOM_GEAR 有效 int
.cropWH()// 裁剪宽高比,设置如果大于图片本身宽高则无效 int
.rotateEnabled() // 裁剪是否可旋转图片 true or false
.scaleEnabled()// 裁剪是否可放大缩小图片 true or false
.videoQuality()// 视频录制质量 0 or 1 int
.videoSecond()// 显示多少秒以内的视频 or 音频也可适用 int
.recordVideoSecond()//视频秒数录制 默认 60s int
.forResult(PictureConfig.CHOOSE_REQUEST);//结果回调 onActivityResult code
//包括裁剪和压缩后的缓存,要在上传成功后调用,注意:需要系统 sd 卡权限
PictureFileUtils.deleteCacheDirFile(MainActivity.this);
**启动相册并拍照**
PictureSelector.create(MainActivity.this)
.openGallery(PictureMimeType.ofImage())
.forResult(PictureConfig.CHOOSE_REQUEST);
**单独启动拍照或视频 根据 PictureMimeType 自动识别**
PictureSelector.create(MainActivity.this)
.openCamera(PictureMimeType.ofImage())
.forResult(PictureConfig.CHOOSE_REQUEST);
**预览图片**
// 预览图片 可自定长按保存路径
PictureSelector.create(MainActivity.this).externalPicturePreview(position, "/custom_file", selectList);
PictureSelector.create(MainActivity.this).externalPicturePreview(position, selectList);
**预览视频**
PictureSelector.create(MainActivity.this).externalPictureVideo(video_path);
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
switch (requestCode) {
case PictureConfig.CHOOSE_REQUEST:
// 图片选择结果回调
selectList = PictureSelector.obtainMultipleResult(data);
// 例如 LocalMedia 里面返回三种 path
// 1.media.getPath(); 为原图 path
// 2.media.getCutPath();为裁剪后 path,需判断 media.isCut();是否为 true
// 3.media.getCompressPath();为压缩后 path,需判断 media.isCompressed();是否为 true
// 如果裁剪并压缩了,以取压缩路径为准,因为是先裁剪后压缩的
adapter.setList(selectList);
adapter.notifyDataSetChanged();
DebugUtil.i(TAG, "onActivityResult:" + selectList.size());
break;
}
}
}
修复裁剪速度慢的问题
v2.0.9
新增图片列表点击缩放效果 api
v2.0.7
修复已知 bug
v2.0.6
#PictureSelector 2.0
-keep class com.luck.picture.lib.** { *; }
-dontwarn com.yalantis.ucrop**
-keep class com.yalantis.ucrop** { *; }
-keep interface com.yalantis.ucrop** { *; }
#rxjava
-dontwarn sun.misc.**
-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
long producerIndex;
long consumerIndex;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
rx.internal.util.atomic.LinkedQueueNode producerNode;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {
rx.internal.util.atomic.LinkedQueueNode consumerNode;
}
#rxandroid
-dontwarn sun.misc.**
-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
long producerIndex;
long consumerIndex;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
rx.internal.util.atomic.LinkedQueueNode producerNode;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {
rx.internal.util.atomic.LinkedQueueNode consumerNode;
}
#glide
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public class * extends com.bumptech.glide.AppGlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
**[] $VALUES;
public *;
}
# for DexGuard only
-keepresourcexmlelements manifest/application/meta-data@value=GlideModule
**腾讯优测-深度测试-通过率达到 100%**