美文网首页
关于使用图片选择器的库的选择

关于使用图片选择器的库的选择

作者: zgfei | 来源:发表于2017-06-02 10:39 被阅读1917次
    前言:

    这几日一直在做图片选择器的功能,关于要求是仿微信的样式,takePhoto 直接被 pass。经过几天的查阅资料和筛选,基本确定了一下相关的几个库来使用。接下来就具体解析一下这几库的相关优缺点,当然也有少不了的坑。

    因为后面写不了,所以就直接写在了介绍里面,不知道为什么编辑帖子的时候,浏览器会莫名崩溃,奈何只能简单的介绍了。

    在图片选择器的选择上,如果有时间可以研究一下源码如何写的,时间充足的话可以自己写一个符合自己项目需要的库。

    相关库介绍

    Matisse

    这是知乎开源的一个框架,查看知乎,也在使用。

    PhotoPicker

    这也是一个比较好用库,作者是 donglua
    写在这:这个库没有实现的功能有多选浏览,浏览时选择等,有一点就是默认的布局有点不好看。因此当时我是直接使用的源码进行的修改,这样可能又会遇到 Matisse 那样的问题,不过按照步骤一般都能解决,这里就不做过多介绍了。

    这里再说一下刷新本地图片保存的文件的方法,这个方法是在 PhotoPicker 的源码中找到的:

    // 重点是获取图片保存的路径
    private void scan(Uri uri) {
        if (!uri.toString().contains("ContentProvider 提供的:authorities")) {
            return;
        }
        String path = uri.getPath();
        String[] split = path.split("/");
    
        File file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);// 文件路径是默认的,要与 ContentProvider 设置的 resource 一致(public/private)
        String a = file.getAbsolutePath() + File.separatorChar + split[split.length - 1];// 截取图片的名称全称(包含路径)
    
        Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);// 扫描的意图
    
        if (TextUtils.isEmpty(file.getAbsolutePath())) {
            return;
        }
    
        File f = new File(a);
        Uri contentUri = Uri.fromFile(f);
        mediaScanIntent.setData(contentUri);
        mActivity.sendBroadcast(mediaScanIntent);// 发送广播
    }
    

    ImageSelector

    这个是高仿微信的一个开源库,这个目前正在维护中,谨慎使用。
    维护的地址是:https://github.com/YancyYe/GalleryPick
    相对来说这个库还是挺不错的,虽然有一些 bug,并且在维护,但是对这个库还是很期待的

    注意:

    Maitsse 返回的数据是以 Uri 的形式进行返回,因此需要自行处理。
    PhotoPicker 返回的是相对路径,可以直接获取。

    对比优缺点
    Matisse

    Matisse 是知乎开源的库,当然兼容性和稳定性还是挺可靠的,这个库的基本使用方法在项目的首页已经介绍的很详细了,这里不再重复,我们只写一些他们没有的。
    在使用这个库的时候我搜索了很多的资料,基本都是照抄官网的,没有一点创新,还好有一位叫七零八落蛋的作者提供了一些有用的知识(感谢感谢)。

    相关支持:查看官方文档
    优点:功能强大,界面美观,稳定性高
    缺点:多选和单选都是跳入同一个图片选择器页面,拍照功能没有独立出来,相关的设置属性没有开放,返回的结果以 Uri 的方式返回……

    如果只是使用一些简单的功能,可以参考官方提供的 demo 即可,这里讲一下添加拍照功能。

    拍照

    在拍照的时候我们需要设置 capture(true) 和 captureStrategy() 方法,这样才会显示出拍照。但是这里需要提供一些配置。
    1、提供一个 ContentProvider 供拍照使用,不然会崩。
    这里是我添加的 ContentProvider

      <provider             
          android:name="com.example.zgfei.photopickertest.zhihu.MyFileProvider"
          android:authorities="com.example.zgfei.photopickertest.provider"
          android:exported="false"
          android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths_public"/>
        </provider>
    

    这里提供了一个 MyFileProvider 用来兼容 android 7.0,不然会崩。这个 MyFileProvider 只是继承自 FileProvider 即可。
    android:authorities="com.example.zgfei.photopickertest.provider" 很重要,这里的 authorities 对应的值要和设置 captureStrategy() 的参数一直,不然会崩。
    看一下我设置的 captureStrategy() 方法:

     Matisse.from(MatisseTestActivity.this).choose(MimeType.allOf())
                .countable(false)
                .capture(true)
                .captureStrategy(new CaptureStrategy(true, "com.example.zgfei.photopickertest.provider"))
                .maxSelectable(9)//最大选择数
                .theme(R.style.Matisse_Zhihu)//主题
                .spanCount(4)//行数
                .restrictOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)
                .thumbnailScale(0.85f)
                .imageEngine(new PicassoEngine())//选择图片加载器
                .forResult(REQUEST_CODE_CHOOSE);//设置回调
    

    这里 android:resource="@xml/file_paths_public" 提供了一个文件的路径,即拍照完成后的路径,路径一定要配置对,不然会崩。
    这个地方提供一些相关的资料供学习使用:
    FileProvider共享文件、缓存
    FileProvider无法获取外置SD卡问题解决方案 | Failed to find configured root that contains
    关于AndroidManifest.xml 添加多个 provider节点问题
    在配置 ContentProvider 的时候会遇到各种各样的问题,这些和上面的相关介绍均可解决问题。
    这样就可以成功拍照了,也可以获取相关的 Uri,那么这个时候另一个问题就会来。

    问题描述:在我们拍完照后,页面会返回我们之前的页面,不会跳到图片选择的页面,这个也就算了,当我们再次进入图片选择页面的时候,刚才拍的照片竟然没有显示出来。崩溃,如果你可以说服你的产品这样做是合理的,那没什么可说的(碰见这样的产品就娶了吧,别管
    TA 是男的还是女的)。

    解决问题:找到保存图片的位置,刷新一下图片的文件,再次进入就可以显示出来了(好神奇,但是有毛用,你不可能告诉用户这样做吧)。

    但是问题出来了,还是要解决的,那么我们就自己刷新吧。网上有相关的刷新相册的相关资料,自己可以 Google。当你看到它返回来的 Uri
    的格式,你就知道我为什么不用网上的资料了。这里说一下我的解决方案。

    刷新拍照图片保存的文件
    查看源码发现图片保存的路径是:
    Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
    getExternalFilesDir(Environment.DIRECTORY_PICTURES);

    源码:
    private File createImageFile() throws IOException {
        // Create an image file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = "JPEG_" + timeStamp + "_";
        File storageDir;
        if (mCaptureStrategy.isPublic) {
            storageDir = Environment.getExternalStoragePublicDirectory(
                    Environment.DIRECTORY_PICTURES);
        } else {
            storageDir = mContext.get().getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        }
        return new File(storageDir + imageFileName + ".jpg");
    }
    

    这里根据你在 file_paths_public.xml 中使用的文件路径可以知道你的 mCaptureStrategy.isPublic 还是 else,获取到路径后刷新就简单了,刷新的方法会在 PhotoPicker 的地方讲。
    使用 Matisse 不使用拍照功能,什么问题都没有,使用,上面全是坑。毕竟人家是拿来完成人家自己的功能,我们如果要用可以学习一下。

    写在最后

    不知道问什么当写到一定长度的时候,浏览器会莫名崩溃,重新进入,依旧是崩溃,因此写不了。

    相关文章

      网友评论

          本文标题:关于使用图片选择器的库的选择

          本文链接:https://www.haomeiwen.com/subject/xslitxtx.html