小红书多图剪裁+微信图片选择器+大图预览+图片剪裁(支持圆形剪裁和镂空剪裁)

Overview

关于YImagePicker

点击查看2.x版本readme

本文档更新于:2020/4/15 上午10点36分

Download

  • 支持小红书多图剪裁、微信多图选择、单图剪裁、多图批量剪裁、大图预览
  • 支持自定义所有UI,包括标题栏、底部栏、列表item、文件夹item、剪裁页面、预览页面等
  • 支持13种视频图片格式混合加载,支持过滤掉指定格式文件
  • 支持大图预览,支持超长图、超大图,拒绝too lagre(已修复单图剪裁长图)
  • 支持自定义剪裁比例、剪裁边距、圆形剪裁、镂空/充满剪裁(仿最新微信图片头像选择)
  • 支持视频多选和预览
  • 支持只选择图片或者视频类型
  • 支持恢复上一次选中的图片状态(微信样式)
  • 支持屏蔽指定媒体文件(微信样式)
  • 选择结果直接回调,拒绝配置ActivityForResult+requestCode,即调用即处理
  • 支持选择器调用失败回调
  • 支持自定义回调类型
  • 支持直接回调媒体相册列表及文件列表
  • 支持选择器所有文案修改、国际化定制
  • 支持多种特殊需求覆盖,支持自定义选择器拦截事件
  • 已全面适配androidQ
  • 支持直接拍摄视频、照片等
  • 轻量级,aar大小不超过300K,无so库,无任何第三方依赖
  • 支持androidx和support
  • 永久维护

引入依赖

androidx版本:

implementation 'com.ypx.yimagepicker:androidx:3.1.4'

support版本:后期可能不再维护,请使用者尽早切换androidx (support依赖最高兼容28)

implementation 'com.ypx.yimagepicker:support:3.1.4.1'

核心原理

YImagePicker与主项目通过IPickerPresenter进行交互与解耦,presenter采用序列化接口的方式实现。使用者需要自行实现presenter的方法。选择器回调采用嵌入fragment的方式实现,类似于Glide或RxPermisson.原理上还是使用OnActivityResult,但无需再配置requestCode并且支持跨进程回调。

调用选择器之前必须实现 IPickerPresenter 接口

选择器问题解答汇总

点击查看3.x详细API文档

apk体验地址 - 密码:123456

效果图集

  • demo效果

demo效果

  • 小红书样式

小红书样式 小红书样式 小红书样式

  • 微信样式

微信样式 微信样式 微信样式

  • 自定义样式

自定义样式 自定义样式

  • 自定义比例剪裁

自定义比例剪裁 自定义比例剪裁

  • 多图剪裁页面(仿aloha)

aloha

微信图片选择

支持视频、GIF、长图选择,支持选择状态保存。调用前请按照demo实现IPickerPresenter接口 ,示例如下: WeChatPresenter

ImagePicker.withMulti(new WeChatPresenter())//指定presenter                                 
        //设置选择的最大数 
        .setMaxCount(9)  
        //设置列数                                                  
        .setColumnCount(4)      
        //设置要加载的文件类型,可指定单一类型  
        .mimeTypes(MimeType.ofAll()) 
        //设置需要过滤掉加载的文件类型 
        .filterMimeTypes(MimeType.GIF)       
        .showCamera(true)//显示拍照 
        .setPreview(true)//开启预览                                                  
        //大图预览时是否支持预览视频
        .setPreviewVideo(true)  
        //设置视频单选                                     
        .setVideoSinglePick(true) 
        //设置图片和视频单一类型选择 
        .setSinglePickImageOrVideoType(true) 
        //当单选或者视频单选时,点击item直接回调,无需点击完成按钮          
        .setSinglePickWithAutoComplete(false)
        //显示原图  
        .setOriginal(true)  
        //显示原图时默认原图选项开关  
        .setDefaultOriginal(false)
        //设置单选模式,当maxCount==1时,可执行单选(下次选中会取消上一次选中)
        .setSelectMode(SelectMode.MODE_SINGLE)   
        //设置视频可选取的最大时长,同时也是视频可录制的最大时长
        .setMaxVideoDuration(1200000L)  
        //设置视频可选取的最小时长                                  
        .setMinVideoDuration(60000L) 
        //设置上一次操作的图片列表,下次选择时默认恢复上一次选择的状态 
        .setLastImageList(null) 
        //设置需要屏蔽掉的图片列表,下次选择时已屏蔽的文件不可选择
        .setShieldList(null)               
        .pick(this, new OnImagePickCompleteListener() {  
            @Override    
            public void onImagePickComplete(ArrayList<ImageItem> items) {          
                //图片选择回调,主线程                  
            }                
        });                                                                                                                              

小红书图片选择

高仿小红书图片剪裁框架,支持视频以及多图剪裁、支持视频预览,支持UI自定义,支持fragment样式侵入。调用前请按照demo实现IPickerPresenter接口 ,示例如下: RedBookPresenter

ImagePicker.withCrop(new RedBookPresenter())//设置presenter                
        .setMaxCount(9)//设置选择数量                                          
        .showCamera(true)//设置显示拍照                                        
        .setColumnCount(4)//设置列数                                         
        .mimeTypes(MimeType.ofImage())//设置需要加载的文件类型                      
        .filterMimeTypes(MimeType.GIF)//设置需要过滤掉的文件类型                     
        .assignGapState(false)//强制留白模式                                   
        .setFirstImageItem(null)//设置上一次选中的图片                             
        .setFirstImageItemSize(1,1)//设置上一次选中的图片地址                        
        .setVideoSinglePick(true)//设置视频单选                                
        .setMaxVideoDuration(1200000L)//设置可选区的最大视频时长                        
        .setMinVideoDuration(60000L)//设置视频可选取的最小时长                       
        .pick(this, new OnImagePickCompleteListener() {                  
            @Override                                                    
            public void onImagePickComplete(ArrayList<ImageItem> items) {
                //图片剪裁回调,主线程                                             
                //注意:剪裁回调里的ImageItem中getCropUrl()才是剪裁过后的图片地址             
            }                                                            
        });                                                       

预览

支持多图预览和自定义预览界面,支持加载大图,超长图和高清图,示例如下:

//配置需要预览的所有图片列表,其中imageitem可替换为Uri或者String(绝对路径)
ArrayList<ImageItem> allPreviewImageList = new ArrayList<>();

//默认选中的图片索引
int defaultPosition = 0;
//开启预览
ImagePicker.preview(this, new WXImgPickerPresenter(), allPreviewImageList, defaultPosition, new OnImagePickCompleteListener() {
        @Override
        public void onImagePickComplete(ArrayList<ImageItem> items) {
            //图片编辑回调,主线程
        }
    });                                                           

拍照 3.1版本已变更

支持直接打开摄像头拍照,3.1版本去除了原有的拍照保存路径,新增了isCopyInDCIM入参,代表是否将拍照的图片copy一份到外部DCIM目录中 因为安卓Q禁止直接写入文件到系统DCIM文件下,所以拍照入参必须是私有目录路径.所以废弃掉原有的imagepath入参 如果想让拍摄的照片写入外部存储中,则需要copy一份文件到DCIM目录中并刷新媒体库 示例如下:

String name="图片名称,不要加后缀";//可为null
boolean isCopyInDCIM=true;//copy一份保存到系统相册文件
ImagePicker.takePhoto(this,name,isCopyInDCIM, new OnImagePickCompleteListener() {
        @Override
        public void onImagePickComplete(ArrayList<ImageItem> items) {
            //拍照回调,主线程
        }
    });
items) { //拍照回调,主线程 } }); " aria-label="Copy" class="ClipboardButton btn js-clipboard-copy m-2 p-0 tooltipped-no-delay" data-copy-feedback="Copied!" data-tooltip-direction="w">

拍摄视频 3.1版本已变更

支持直接打开摄像头拍视频,3.1已变更,变更理由参考拍照 示例如下:

String name="视频名称,不要加后缀";//可为null
long maxDuration=10000l;//可录制的最大时常,单位毫秒ms
boolean isCopyInDCIM=true;//copy一份保存到系统相册文件
ImagePicker.takeVideo(this,name,maxDuration, isCopyInDCIM,new OnImagePickCompleteListener() {
        @Override
        public void onImagePickComplete(ArrayList<ImageItem> items) {
            //视频回调,主线程
        }
    });
items) { //视频回调,主线程 } }); " aria-label="Copy" class="ClipboardButton btn js-clipboard-copy m-2 p-0 tooltipped-no-delay" data-copy-feedback="Copied!" data-tooltip-direction="w">

调用选择器并剪裁

支持选择图片完调用剪裁,支持自定义比例剪裁,支持圆形剪裁,示例如下:

ImagePicker.withMulti(new WeChatPresenter())
           .mimeTypes(MimeType.ofImage())
           .filterMimeTypes(MimeType.GIF)
           //剪裁完成的图片是否保存在DCIM目录下
           //true:存储在DCIM下 false:存储在 data/包名/files/imagePicker/ 目录下
           .cropSaveInDCIM(false)
            //设置剪裁比例
           .setCropRatio(1,1)
           //设置剪裁框间距,单位px
           .cropRectMinMargin(50)
            //是否圆形剪裁,圆形剪裁时,setCropRatio无效
           .cropAsCircle()
            //设置剪裁模式,留白或充满  CropConfig.STYLE_GAP 或 CropConfig.STYLE_FILL
           .cropStyle(CropConfig.STYLE_FILL)
            //设置留白模式下生成的图片背景色,支持透明背景
           .cropGapBackgroundColor(Color.TRANSPARENT)
           .crop(this, new OnImagePickCompleteListener() {
               @Override
               public void onImagePickComplete(ArrayList<ImageItem> items) {
                   //图片剪裁回调,主线程
               }
           });                                                   

拍照并剪裁

支持直接打开摄像头拍照并剪裁,支持自定义比例剪裁和圆形剪裁,示例如下:

//配置剪裁属性
CropConfig cropConfig = new CropConfig();
//设置上一次剪裁矩阵位置信息,用于恢复上一次剪裁,Info类型从imageitem或者cropimageview中取,可为null
cropConfig.setCropRestoreInfo(new Info());
 //设置剪裁比例
cropConfig.setCropRatio(1, 1);
//设置剪裁框间距,单位px
cropConfig.setCropRectMargin(100);
//是否保存到DCIM目录下,false时会生成在 data/files/imagepicker/ 目录下
cropConfig.saveInDCIM(false);
//是否圆形剪裁,圆形剪裁时,setCropRatio无效
cropConfig.setCircle(false);
//设置剪裁模式,留白或充满  CropConfig.STYLE_GAP 或 CropConfig.STYLE_FILL
cropConfig.setCropStyle(CropConfig.STYLE_GAP);
//设置留白模式下生成的图片背景色,支持透明背景
cropConfig.setCropGapBackgroundColor(Color.TRANSPARENT );
//调用拍照
ImagePicker.takePhotoAndCrop(this, new WXImgPickerPresenter(), cropConfig, 
    new OnImagePickCompleteListener() {
        @Override
        public void onImagePickComplete(ArrayList<ImageItem> items) {
            //剪裁回调,主线程
        }
    });

直接剪裁

支持直接跳转剪裁页面,示例如下:

CropConfig cropConfig = new CropConfig();
//设置上一次剪裁矩阵位置信息,用于恢复上一次剪裁,Info类型从imageitem或者cropimageview中取,可为null
cropConfig.setCropRestoreInfo(new Info());
 //设置剪裁比例
cropConfig.setCropRatio(1, 1);
//设置剪裁框间距,单位px
cropConfig.setCropRectMargin(100);
//是否保存到DCIM目录下,false时会生成在 data/files/imagepicker/ 目录下
cropConfig.saveInDCIM(false);
//是否圆形剪裁,圆形剪裁时,setCropRatio无效
cropConfig.setCircle(false);
//设置剪裁模式,留白或充满  CropConfig.STYLE_GAP 或 CropConfig.STYLE_FILL
cropConfig.setCropStyle(CropConfig.STYLE_GAP);
//设置留白模式下生成的图片背景色,支持透明背景
cropConfig.setCropGapBackgroundColor(Color.TRANSPARENT );
//调用剪裁
String needCropImageUrl="需要剪裁的图片路径";
ImagePicker.crop(this, new WXImgPickerPresenter(), cropConfig, needCropImageUrl,
    new OnImagePickCompleteListener() {
        @Override
        public void onImagePickComplete(ArrayList<ImageItem> items) {
            //剪裁回调,主线程
        }
    });
items) { //剪裁回调,主线程 } }); " aria-label="Copy" class="ClipboardButton btn js-clipboard-copy m-2 p-0 tooltipped-no-delay" data-copy-feedback="Copied!" data-tooltip-direction="w">

提供媒体数据——支持回调相册数据、所有媒体数据、指定相册内媒体数据

获取媒体相册数据

//指定要回调的相册类型,可以指定13种图片视频文件格式混合
Set<MimeType> mimeTypes = MimeType.ofAll();
ImagePicker.provideMediaSets(this, mimeTypes, new MediaSetsDataSource.MediaSetProvider() {
    @Override
    public void providerMediaSets(ArrayList<ImageSet> imageSets) {
        //相册列表回调,主线程
    }
});

获取全部媒体文件

//指定要回调的相册类型,可以指定13种图片视频文件格式混合
Set<MimeType> mimeTypes = MimeType.ofAll();
ImagePicker.provideAllMediaItems(this, mimeTypes, new MediaItemsDataSource.MediaItemProvider() {
        @Override
        public void providerMediaItems(ArrayList<ImageItem> imageItems, ImageSet allVideoSet) {
            //全部媒体数据回调,主线程
            //只有当mimeTypes既包含图片或者视频格式文件时,allVideoSet才有值
        }
    });

获取指定相册内全部媒体文件

//指定要回调的相册类型,可以指定13种图片视频文件格式混合
Set<MimeType> mimeTypes = MimeType.ofAll();
//指定相册,id不能为空
ImageSet imageSet = new ImageSet();
ImagePicker.provideMediaItemsFromSet(this, imageSet, mimeTypes, new MediaItemsDataSource.MediaItemProvider() {
        @Override
        public void providerMediaItems(ArrayList<ImageItem> imageItems, ImageSet allVideoSet) {
            //全部媒体数据回调,主线程
            //只有当mimeTypes既包含图片或者视频格式文件时,allVideoSet才有值
        }
    });

预加载获取指定相册内全部媒体文件

//指定要回调的相册类型,可以指定13种图片视频文件格式混合
Set<MimeType> mimeTypes = MimeType.ofAll();
//指定相册,id不能为空
ImageSet imageSet = new ImageSet();
//预加载个数
int preloadSize = 40;
ImagePicker.provideMediaItemsFromSetWithPreload(this, imageSet, mimeTypes, preloadSize, 
    new MediaItemsDataSource.MediaItemPreloadProvider() {
        @Override
        public void providerMediaItems(ArrayList<ImageItem> imageItems) {
            //预加载回调,预先加载指定数目的媒体文件回调
        }
    },
    new MediaItemsDataSource.MediaItemProvider() {
        @Override
        public void providerMediaItems(ArrayList<ImageItem> imageItems, ImageSet allVideoSet) {
            //所有媒体文件回调
            }
        });

使用前请务必阅读选择器问题解答汇总以及 3.x使用文档

版本记录

查看详细版本记录

3.1.4版本 [2020.04.15]

  1. 修复3.1.3版本path取不到绝对路径问题
  2. 修复quicktime类型视频无法过滤的问题

3.1.3版本 [2020.04.09]

  1. 修复安卓10上全部视频文件夹缩略图不展示
  2. 修复安卓10上部分手机上部分图片无法展示问题
  3. 修复大图预览放大缩小卡顿问题
  4. 彻底修复toolarge闪退
  5. 优化了图片剪裁预览质量
  6. 修复预览界面无法预览视频问题
  7. 预览支持自定义预览item,可根据图片还是视频动态显示布局
  8. presenter的interceptItemClick方法新增isClickCheckBox入参,代表拦截的对象是否是点击右上角checkbox
  9. 新增showCameraOnlyInAllMediaSet方法代表是否只在全部文件夹里才展示拍照item,其他文件夹不展示
  10. imageitem新增displayName字段代表文件名称
  11. 其他更多细节优化

3.1版本 [2020.02.24]

  1. [优化]isOriginalImage加入到imageitem里
  2. [变更]自定义文本统一,删除了PickerConstants类,presenter中无需对选择器文案进行修改,若需要修改文案,则直接复制imagepicker中string文件,另外demo已覆盖英文适配
  3. [优化]多图剪裁已加入demo(AlohaActivity)
  4. [bug修复]长图剪裁崩溃问题
  5. [bug修复]关闭屏幕旋转问题
  6. [新增]新增setDefaultOriginal用于设置此次打开选择器的默认原图开关
  7. [新增]单图剪裁支持保存状态,下次恢复
  8. [新增]录制视频添加最大时长配置
  9. [优化]完全兼容androudQ拍照问题
  10. [新增]UiPickerConfig新增主题色设置
  11. [优化]demo架构调整,使用者参考更清晰

下个版本排期

时间:暂定2020年5月中旬

  1. 剪裁支持输出大小
  2. 剪裁支持旋转(尽量)
  3. 文件大小加载限制
  4. 支持darkmode模式
  5. 支持activity自定义跳转动画
  6. 内置新版本微信样式,知乎样式等
  7. 支持切换视频底层框架(吐槽:官方videoView太难用了~~/(ㄒoㄒ)/~~)
  8. 等你来提

永不TODO:

  1. 不会支持图片压缩,请使用者自行使用luBan
  2. 不会支持图片和视频高级编辑(滤镜、贴纸等)

感谢

  • 本框架媒体库查询部分借鉴于知乎开源框架Matisee,并在其基础上拓展并延伸,让查询更富有定制性,在此对Matisee原作者表示感谢。

  • 本库来源于mars App,想要体验城市最新的吃喝玩乐,欢迎读者下载体验mars!

  • 感谢所有支持或star本项目的使用者,感谢所有给我提issue的朋友们 !

心声

YImagePicker从当初的只支持微信图片选择器到支持小红书样式,再到各种自定义,可谓花费了我近一年多的时光,可能有人觉得这个项目很简单,但是从开源性的角度上来说,很多时候代码不是我们想怎么写就怎么写的。为了达成统一风格,本人也借鉴了不下于20多个图片选择库。但是随着业务的复杂和机型的多样,不得不一遍遍重构,其中带来了不少的问题,也学习到了很多。在我的计划中,本库3.0版本算是一次较大的更新,相比2.x有着更优异的稳定性和定制性。但这绝不是最优版本,随着越来越多的定制化需求,架构可能会面临一次又一次的更新。所以使用者在使用的过程中如果出现各种各样的问题,还请不要放弃本库,可以直接加我联系方式并反馈给我(喷我),如果有更好的建议,也可以给我提request,我们一起完善此框架。最后说一句,没有什么是完美的,但我会力所能及~

遇到问题别绕路,QQ微信直接呼~ 您的star就是我前进的动力~ 🌹

Comments
  • 选择图片的页面闪退,没错误日志

    选择图片的页面闪退,没错误日志

    完整日志如下:

    2019-11-01 14:53:04.331 6661-6661/com.zkzz.app.launcher D/CrashReport: >>> com.zkzz.module.browser.ui.BrowserMainActivity onPaused <<< 2019-11-01 14:53:04.332 6661-6661/com.zkzz.app.launcher I/CrashReport-Native: Set native info: isAppForeground(false) 2019-11-01 14:53:04.332 6661-6661/com.zkzz.app.launcher D/WebView: onPause 2019-11-01 14:53:04.395 6661-6661/com.zkzz.app.launcher D/AndroidAutoSize: com.ypx.imagepicker.activity.multi.MultiImagePickerActivity used the global configuration. 2019-11-01 14:53:04.396 6661-6661/com.zkzz.app.launcher D/AndroidAutoSize: The com.ypx.imagepicker.activity.multi.MultiImagePickerActivity has been adapted! MultiImagePickerActivity Info: isBaseOnWidth = true, designWidthInDp = 1280.000000, designWidthInSubunits = 1280.000000, targetDensity = 1.000000, targetScaledDensity = 1.000000, targetDensityDpi = 160, targetXdpi = 1.000000 2019-11-01 14:53:04.397 6661-6661/com.zkzz.app.launcher D/CrashReport: >>> com.ypx.imagepicker.activity.multi.MultiImagePickerActivity onCreated <<< 2019-11-01 14:53:04.414 6661-6661/com.zkzz.app.launcher D/AndroidAutoSize: com.ypx.imagepicker.activity.multi.MultiImagePickerActivity used the global configuration. 2019-11-01 14:53:04.414 6661-6661/com.zkzz.app.launcher D/AndroidAutoSize: The com.ypx.imagepicker.activity.multi.MultiImagePickerActivity has been adapted! MultiImagePickerActivity Info: isBaseOnWidth = true, designWidthInDp = 1280.000000, designWidthInSubunits = 1280.000000, targetDensity = 1.000000, targetScaledDensity = 1.000000, targetDensityDpi = 160, targetXdpi = 1.000000 2019-11-01 14:53:04.415 6661-6661/com.zkzz.app.launcher D/AndroidAutoSize: com.ypx.imagepicker.activity.multi.MultiImagePickerFragment used the global configuration. 2019-11-01 14:53:04.416 6661-6661/com.zkzz.app.launcher D/AndroidAutoSize: The com.ypx.imagepicker.activity.multi.MultiImagePickerActivity has been adapted! MultiImagePickerActivity Info: isBaseOnWidth = true, designWidthInDp = 1280.000000, designWidthInSubunits = 1280.000000, targetDensity = 1.000000, targetScaledDensity = 1.000000, targetDensityDpi = 160, targetXdpi = 1.000000 2019-11-01 14:53:04.446 6661-6661/com.zkzz.app.launcher D/CrashReport: >>> com.ypx.imagepicker.activity.multi.MultiImagePickerActivity onResumed <<< 2019-11-01 14:53:04.447 6661-6661/com.zkzz.app.launcher I/CrashReport-Native: Set native info: isAppForeground(true) 2019-11-01 14:53:04.453 6661-6661/com.zkzz.app.launcher V/PhoneWindow: DecorView setVisiblity: visibility = 4, Parent = null, this = DecorView@4b997cd[] 2019-11-01 14:53:04.454 6661-6661/com.zkzz.app.launcher D/WindowClient: Add to mViews: DecorView@4b997cd[MultiImagePickerActivity], this = android.view.WindowManagerGlobal@e7d2c39 2019-11-01 14:53:04.459 6661-6721/com.zkzz.app.launcher D/OpenGLRenderer: CanvasContext() 0x947cc5c0 2019-11-01 14:53:04.464 6661-6661/com.zkzz.app.launcher D/ViewRootImpl[MultiImagePickerActivity]: hardware acceleration is enabled, this = ViewRoot{ac04f06 com.zkzz.app.launcher/com.ypx.imagepicker.activity.multi.MultiImagePickerActivity,ident = 10} 2019-11-01 14:53:04.472 6661-6661/com.zkzz.app.launcher V/PhoneWindow: DecorView setVisiblity: visibility = 0, Parent = ViewRoot{ac04f06 com.zkzz.app.launcher/com.ypx.imagepicker.activity.multi.MultiImagePickerActivity,ident = 10}, this = DecorView@4b997cd[MultiImagePickerActivity] 2019-11-01 14:53:04.518 6661-6721/com.zkzz.app.launcher D/OpenGLRenderer: CanvasContext() 0x947cc5c0 initialize window=0x93e0e000, title=com.zkzz.app.launcher/com.ypx.imagepicker.activity.multi.MultiImagePickerActivity 2019-11-01 14:53:04.518 6661-6661/com.zkzz.app.launcher D/Surface: Surface::allocateBuffers(this=0x93e0e000) 2019-11-01 14:53:04.518 6661-6721/com.zkzz.app.launcher D/Surface: Surface::connect(this=0x93e0e000,api=1) 2019-11-01 14:53:04.520 6661-6721/com.zkzz.app.launcher W/libEGL: [ANDROID_RECORDABLE] format: 1 2019-11-01 14:53:04.542 6661-6721/com.zkzz.app.launcher D/IMGSRV: GrallocRegisterBuffer:1878: hnd=0x9442ad00 ID=120451 fd=133 ref=1 bufferID=1351694 2019-11-01 14:53:04.569 6661-6661/com.zkzz.app.launcher V/InputMethodManager: onWindowFocus: android.support.v7.widget.RecyclerView{70bf98a VFED..... .F.....D 0,0-1280,689 #7f0700e5 app:id/mRecyclerView} softInputMode=272 first=true flags=#81810100 2019-11-01 14:53:04.578 6661-6721/com.zkzz.app.launcher D/IMGSRV: GrallocRegisterBuffer:1878: hnd=0x9442ad80 ID=120455 fd=125 ref=1 bufferID=1352717 2019-11-01 14:53:04.589 6661-6661/com.zkzz.app.launcher D/CrashReport: >>> com.ypx.imagepicker.activity.multi.MultiImagePickerActivity onPaused <<< 2019-11-01 14:53:04.591 6661-6661/com.zkzz.app.launcher I/CrashReport-Native: Set native info: isAppForeground(false) 2019-11-01 14:53:04.631 6661-6721/com.zkzz.app.launcher D/Surface: Surface::disconnect(this=0x93dd0800,api=1) 2019-11-01 14:53:04.631 6661-6721/com.zkzz.app.launcher D/IMGSRV: GrallocUnregisterBuffer:1974: bFree=0 ID=115866 ref=1 2019-11-01 14:53:04.631 6661-6721/com.zkzz.app.launcher D/IMGSRV: GrallocUnregisterBuffer:1974: bFree=0 ID=115779 ref=1 2019-11-01 14:53:04.632 6661-6721/com.zkzz.app.launcher D/IMGSRV: GrallocUnregisterBuffer:1974: bFree=0 ID=115773 ref=1 2019-11-01 14:53:04.643 6661-6661/com.zkzz.app.launcher D/CrashReport: >>> com.ypx.imagepicker.activity.multi.MultiImagePickerActivity onDestroyed <<< 2019-11-01 14:53:04.649 6661-6721/com.zkzz.app.launcher D/Surface: Surface::disconnect(this=0x93e0e000,api=1) 2019-11-01 14:53:04.649 6661-6721/com.zkzz.app.launcher D/IMGSRV: GrallocUnregisterBuffer:1974: bFree=0 ID=120455 ref=1 2019-11-01 14:53:04.650 6661-6721/com.zkzz.app.launcher D/IMGSRV: GrallocUnregisterBuffer:1974: bFree=0 ID=120451 ref=1 2019-11-01 14:53:04.657 6661-6661/com.zkzz.app.launcher D/WindowClient: Remove from mViews: DecorView@4b997cd[MultiImagePickerActivity], this = android.view.WindowManagerGlobal@e7d2c39 2019-11-01 14:53:04.658 6661-6661/com.zkzz.app.launcher D/CrashReport: >>> com.zkzz.module.browser.ui.BrowserMainActivity onResumed <<< 2019-11-01 14:53:04.660 6661-6661/com.zkzz.app.launcher I/CrashReport-Native: Set native info: isAppForeground(true) 2019-11-01 14:53:04.661 6661-6661/com.zkzz.app.launcher D/WebView: onResume 2019-11-01 14:53:04.662 6661-6661/com.zkzz.app.launcher V/PhoneWindow: DecorView setVisiblity: visibility = 0, Parent = ViewRoot{776122e com.zkzz.app.launcher/com.zkzz.module.browser.ui.BrowserMainActivity,ident = 4}, this = DecorView@737681e[BrowserMainActivity] 2019-11-01 14:53:04.663 6661-6661/com.zkzz.app.launcher V/InputMethodManager: onWindowFocus: wendu.dsbridge.DWebView{93c2585 VFEDHVC.. .F...... 0,0-1280,800 #7f0700fb app:id/mWebView} softInputMode=18 first=true flags=#85810100 2019-11-01 14:53:04.676 6661-6721/com.zkzz.app.launcher D/OpenGLRenderer: CanvasContext() 0x9443b700 initialize window=0x93dd0800, title=com.zkzz.app.launcher/com.zkzz.module.browser.ui.BrowserMainActivity 2019-11-01 14:53:04.676 6661-6661/com.zkzz.app.launcher D/Surface: Surface::allocateBuffers(this=0x93dd0800) 2019-11-01 14:53:04.676 6661-6721/com.zkzz.app.launcher D/Surface: Surface::connect(this=0x93dd0800,api=1) 2019-11-01 14:53:04.677 6661-6721/com.zkzz.app.launcher W/libEGL: [ANDROID_RECORDABLE] format: 1 2019-11-01 14:53:04.701 6661-6721/com.zkzz.app.launcher D/IMGSRV: GrallocRegisterBuffer:1878: hnd=0x9442aa00 ID=120468 fd=132 ref=1 bufferID=1356809 2019-11-01 14:53:04.712 6661-6661/com.zkzz.app.launcher V/InputMethodManager: onWindowFocus: wendu.dsbridge.DWebView{93c2585 VFEDHVC.. .F....ID 0,0-1280,800 #7f0700fb app:id/mWebView} softInputMode=18 first=false flags=#85810100 2019-11-01 14:53:04.728 6661-6721/com.zkzz.app.launcher D/IMGSRV: GrallocRegisterBuffer:1878: hnd=0x9442ac00 ID=120474 fd=148 ref=1 bufferID=1357832

    opened by wmailn 8
  • Android10 上 item.isUriPath 判断错误问题

    Android10 上 item.isUriPath 判断错误问题

    debug 看了下,在 Android10 上返回的是 false,看源码判断是根据 path 判断的,但是 path获取的是真实路径,不包含 content://, getUri 是根据 uriPath 解析的,这里才是包含 content://,所以这里是不是应该改下

        public boolean isUriPath() {
            return path != null && path.contains("content://");
        }
    
        public Uri getUri() {
            if (uriPath != null && uriPath.length() > 0) {
                return Uri.parse(uriPath);
            }
    
            if (isUriPath()) {
                return Uri.parse(path);
            }
    
            return PBitmapUtils.getContentUri(mimeType, id);
        }
    
    opened by lzan13 6
  • 大佬 发现一个崩溃的问题

    大佬 发现一个崩溃的问题

    MediaPreviewActivity 这个没有注册Demo里面 导致不能远程依赖,只能用Moudle依赖改XML文件,在里面注册MediaPreviewActivity ,才不崩溃,还有源码SingleCropActivity这个报红,原因是activity.SingleCrop在这个包下 而不是multi这个包

    opened by dingliufan 6
  • 每次打开图片选择isOriginalImage都被初始化为false

    每次打开图片选择isOriginalImage都被初始化为false

    作者你好,每次打开图片选择时,都会在MultiImagePickerFragment的onViewCreated方法中把isOriginalImage初始化为false。 个人认为这个操作不合理,比如用户在预览页面或者图片选择页面修改isOriginalImage为true后,再进入图片选择器,又改成了默认的false。 建议可以把ImagePicker.isOriginalImage = false;这句代码删掉,或采用其他更好的方式。希望采纳。

    In the plan 
    opened by zhangsange 5
  •  全部视频文件夹预览图加载问题

    全部视频文件夹预览图加载问题

    allVideoSet.coverPath = allVideoItems.get(0).path;
    displayCoverImage(String coverUrl, IPickerPresenter presenter) 在Android10上只传路径加载不了图库视频,需要多加个uripath吧

    opened by abcdisgreat 3
  • 想问下里面用到的AndroidX版本是1.1.0吗?

    想问下里面用到的AndroidX版本是1.1.0吗?

    想问下里面用到的AndroidX版本是1.1.0吗? 1.1.0会有问题,具体问题可参考https://stackoverflow.com/questions/58209943/how-to-fix-boolean-androidx-fragment-app-fragmentmanagerimpl-isdestroyed-on 如果AndroidX切换成1.0.2版本则不会出现

    因为我项目中是遇到过这样的问题,所以切换成1.0.2了,但是引入YImagePicker后又出现了,所以想问是不是这个原因?如果是的话能否麻烦切换下AndroidX版本

    opened by LiuDongCai 3
  •  java.lang.RuntimeException: Parcelable encountered IOException writing serializable object

    java.lang.RuntimeException: Parcelable encountered IOException writing serializable object

    你好,我这边采用自定义 模式,发现2部手机都有问题,能看看是啥问题么? 手机型号荣耀V30Pro,magic emui:3.0.1 , 小米mix2 ,miui:11 操作: takePhotoAndCrop,点击相册,成功拍照,拍照页面点击右上角 进入裁剪页面时报错 java.lang.RuntimeException: Failure delivering result ResultInfo{who=android:fragment:1, request=9048, result=-1, data=null} to activity {com.zzgx.zyly_client/com.zzgx.zyly_client.ui.home.HomeActivity}: java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = com.zzgx.zyly_client.ui.home.UserFragment$3) at android.app.ActivityThread.deliverResults(ActivityThread.java:5492) at android.app.ActivityThread.handleSendResult(ActivityThread.java:5533) at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:51) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:149) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:103) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2401) at android.os.Handler.dispatchMessage(Handler.java:107) at android.os.Looper.loop(Looper.java:213) at android.app.ActivityThread.main(ActivityThread.java:8210) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101) Caused by: java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = com.zzgx.zyly_client.ui.home.UserFragment$3) at android.os.Parcel.writeSerializable(Parcel.java:1833) at android.os.Parcel.writeValue(Parcel.java:1780) at android.os.Parcel.writeArrayMapInternal(Parcel.java:928) at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1588) at android.os.Bundle.writeToParcel(Bundle.java:1253) at android.os.Parcel.writeBundle(Parcel.java:997) at android.content.Intent.writeToParcel(Intent.java:10735) at android.app.IActivityTaskManager$Stub$Proxy.startActivity(IActivityTaskManager.java:3860) at android.app.Instrumentation.execStartActivity(Instrumentation.java:1887) at android.app.Activity.startActivityForResult(Activity.java:6147) at android.app.Activity.startActivityFromFragment(Activity.java:6115) at android.app.Activity$HostCallbacks.onStartActivityFromFragment(Activity.java:8918) at android.app.Fragment.startActivityForResult(Fragment.java:1128) at android.app.Fragment.startActivityForResult(Fragment.java:1117) at com.ypx.imagepicker.helper.launcher.PRouter.startActivityForResult(PRouter.java:37) at com.ypx.imagepicker.helper.launcher.PLauncher.startActivityForResult(PLauncher.java:95) at com.ypx.imagepicker.activity.singlecrop.SingleCropActivity.intentCrop(SingleCropActivity.java:82) at com.ypx.imagepicker.ImagePicker$1.onImagePickComplete(ImagePicker.java:142) at com.ypx.imagepicker.helper.CameraCompat$1.onActivityResult(CameraCompat.java:76) at com.ypx.imagepicker.helper.launcher.PRouter.onActivityResult(PRouter.java:61) at android.app.Activity.dispatchActivityResult(Activity.java:8439) at android.app.ActivityThread.deliverResults(ActivityThread.java:5485) at android.app.ActivityThread.handleSendResult(ActivityThread.java:5533)  at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:51)  at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:149)  at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:103)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2401)  at android.os.Handler.dispatchMessage(Handler.java:107)  at android.os.Looper.loop(Looper.java:213)  at android.app.ActivityThread.main(ActivityThread.java:8210)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)  Caused by: java.io.NotSerializableException: com.zzgx.zyly_client.ui.home.UserFragment at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1240) at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1604) at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1565) at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1488) at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1234) at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:354) at android.os.Parcel.writeSerializable(Parcel.java:1828) at android.os.Parcel.writeValue(Parcel.java:1780)  at android.os.Parcel.writeArrayMapInternal(Parcel.java:928)  at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1588)  at android.os.Bundle.writeToParcel(Bundle.java:1253)  at android.os.Parcel.writeBundle(Parcel.java:997)  at android.content.Intent.writeToParcel(Intent.java:10735)  at android.app.IActivityTaskManager$Stub$Proxy.startActivity(IActivityTaskManager.java:3860)  at android.app.Instrumentation.execStartActivity(Instrumentation.java:1887)  at android.app.Activity.startActivityForResult(Activity.java:6147)  at android.app.Activity.startActivityFromFragment(Activity.java:6115)  at android.app.Activity$HostCallbacks.onStartActivityFromFragment(Activity.java:8918)  at android.app.Fragment.startActivityForResult(Fragment.java:1128)  at android.app.Fragment.startActivityForResult(Fragment.java:1117)  at com.ypx.imagepicker.helper.launcher.PRouter.startActivityForResult(PRouter.java:37)  at com.ypx.imagepicker.helper.launcher.PLauncher.startActivityForResult(PLauncher.java:95)  at com.ypx.imagepicker.activity.singlecrop.SingleCropActivity.intentCrop(SingleCropActivity.java:82)  at com.ypx.imagepicker.ImagePicker$1.onImagePickComplete(ImagePicker.java:142)  at com.ypx.imagepicker.helper.CameraCompat$1.onActivityResult(CameraCompat.java:76)  at com.ypx.imagepicker.helper.launcher.PRouter.onActivityResult(PRouter.java:61)  at android.app.Activity.dispatchActivityResult(Activity.java:8439)  at android.app.ActivityThread.deliverResults(ActivityThread.java:5485)  at android.app.ActivityThread.handleSendResult(ActivityThread.java:5533)  at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:51)  at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:149)  at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:103)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2401)  at android.os.Handler.dispatchMessage(Handler.java:107)  at android.os.Looper.loop(Looper.java:213)  at android.app.ActivityThread.main(ActivityThread.java:8210)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101) 

    opened by as1105 3
  • 大家有遇到过这个错误吗?

    大家有遇到过这个错误吗?

    ``

    10-12 21:33:37.468 15487 17616 E AndroidRuntime: java.lang.IllegalStateException: attempt to re-open an already-closed object: /data/user/0/com.android.providers.media/databases/external.db {0}

    15510-12 21:33:37.468 15487 17616 E AndroidRuntime: at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55) 15610-12 21:33:37.468 15487 17616 E AndroidRuntime: at android.database.CursorWindow.getNumRows(CursorWindow.java:252) 15710-12 21:33:37.468 15487 17616 E AndroidRuntime: at android.database.BulkCursorToCursorAdaptor.onMove(BulkCursorToCursorAdaptor.java:81) 15810-12 21:33:37.468 15487 17616 E AndroidRuntime: at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:237) 15910-12 21:33:37.468 15487 17616 E AndroidRuntime: at android.database.AbstractCursor.moveToNext(AbstractCursor.java:275) 16010-12 21:33:37.468 15487 17616 E AndroidRuntime: at android.database.CursorWrapper.moveToNext(CursorWrapper.java:202) 16110-12 21:33:37.468 15487 17616 E AndroidRuntime: at com.ypx.imagepicker.data.MediaItemsDataSource$1.run(MediaItemsDataSource.java:190) 16210-12 21:33:37.468 15487 17616 E AndroidRuntime: at java.lang.Thread.run(Thread.java:764)

    opened by xxzgithub 0
  • 选中 单选,且 设置 单选时,点击item直接回调 出现问题

    选中 单选,且 设置 单选时,点击item直接回调 出现问题

    在 setSelectMode 为 SelectMode.MODE_SINGLE,且 setSinglePickWithAutoComplete 为true的情况下, 在图片选择完跳转到自定义页面时,此时点击 返回 再点击其他列表的item 会提示 只能选一个视频。 查看了下源码 发现在 PickerItemDisableCode的 getItemDisableCode() 里面 PickerItemDisableCode.DISABLE_VIDEO_ONLY_SINGLE_PICK 这个参数 判断有漏洞,缺少了 !selectConfig.isSinglePickAutoComplete()这个判断,我加上就可以了 !

    这里 贴出修改后的代码

    public static int getItemDisableCode(ImageItem imageItem, BaseSelectConfig selectConfig, ArrayList selectList, boolean isContainsThisItem) { boolean isItemEnable = true; int disableCode = PickerItemDisableCode.NORMAL;

        //如果在屏蔽列表中,代表不可选择
        if (selectConfig.isShieldItem(imageItem)) {
            isItemEnable = false;
            disableCode = PickerItemDisableCode.DISABLE_IN_SHIELD;
        }
    
        //如果是视频item
        if (imageItem.isVideo()) {
            //如果只能选择图片和视频类型一种,并且当前已经选择了图片,则该视频不可以选中
            if (isItemEnable
                    && selectConfig.isSinglePickImageOrVideoType()
                    && selectedFirstItemIsImage(selectList)) {
                isItemEnable = false;
                disableCode = PickerItemDisableCode.DISABLE_ONLY_SELECT_IMAGE;
            }
            //视频时长不符合选择条件
            else if (isItemEnable
                    && imageItem.duration > selectConfig.getMaxVideoDuration()) {
                isItemEnable = false;
                disableCode = PickerItemDisableCode.DISABLE_VIDEO_OVER_MAX_DURATION;
            } else if (isItemEnable
                    && imageItem.duration < selectConfig.getMinVideoDuration()) {
                isItemEnable = false;
                disableCode = PickerItemDisableCode.DISABLE_VIDEO_LESS_MIN_DURATION;
            }
            //如果视频只能单选并且已经选过视频
            else if (isItemEnable
                    && selectConfig.isVideoSinglePick()
              /***************************************        新增该判断      ***************************************/
                    && !selectConfig.isSinglePickAutoComplete()
                    && isSelectedListContainsVideo(selectList)
                    && !isContainsThisItem) {
                isItemEnable = false;
                disableCode = PickerItemDisableCode.DISABLE_VIDEO_ONLY_SINGLE_PICK;
            }
        }
        //如果是图片item
        else {
            //如果只能选择图片和视频类型一种,并且当前已经选择了视频,则该图片不可以选中
            if (selectConfig.isSinglePickImageOrVideoType()
                    && selectedFirstItemIsVideo(selectList)) {
                isItemEnable = false;
                disableCode = PickerItemDisableCode.DISABLE_ONLY_SELECT_VIDEO;
            }
        }
    
        //已经超过最大选中数量
        if (isItemEnable && hasSelectedList(selectList) && selectList.size() >= selectConfig.getMaxCount()
                && !isContainsThisItem) {
            disableCode = PickerItemDisableCode.DISABLE_OVER_MAX_COUNT;
        }
    
        return disableCode;
    }
    
    opened by smileToWxm 0
  • 选择仅视频时,第一次无拍照权限,点击 拍摄按钮,申请通过后,会进入 拍照页面(应当进入 录像页面)

    选择仅视频时,第一次无拍照权限,点击 拍摄按钮,申请通过后,会进入 拍照页面(应当进入 录像页面)

    在 PBaseLoaderFragment 的 checkTakePhotoOrVideo时,进入 takeVideo,如果此时没有 相机权限,则会弹窗,允许之后会进入到 拍照页面(我是选择了录像), 原因是 在调用 requestPermissions方法时,传递的参数是 REQ_CAMERA并没有根据当前是视频还是 拍照所区分,而在权限回调之后 的处理 都是 跳拍照页面。导致错误

    opened by smileToWxm 0
Owner
杨培星
专注安卓开发,致力于打造最简单最实用的开源控件~ 开源是一种美德,分享是一种快乐~
杨培星