Matisse Android 图片选择器

5786002 7年前
   <p><img src="https://simg.open-open.com/show/cdc59810c7219e46e9be11f78b4ad5e8.jpg"></p>    <p>很多 App 都有选取图片的需求,例如在 IM 中发送图片,在内容编辑的时候插入图片。Android 系统中的组件可以帮助我们大大减少开发负担,我们可以通过</p>    <pre>  <code class="language-java">Intent toGallery = new Intent(Intent.ACTION_GET_CONTENT);  toGallery.setType("image/*");  toGallery.addCategory(Intent.CATEGORY_OPENABLE);  startActivityForResult(toGallery, REQUEST_GALLERY);</code></pre>    <p>打开系统中支持文件选择的 Activity 选择图片。但是如果我们想要更符合业务场景的界面和交互,同时保证不同移动平台上的体验一致,上面这种做法就不能满足需求了。于是我们选择实现自己的图片选择器 Matisse。</p>    <p>让我们先来看看 Matisse 图片选择器是什么样子:</p>    <p><img src="https://simg.open-open.com/show/6c444a02ed5ff2e49073de345f2f7bb5.jpg"> <img src="https://simg.open-open.com/show/8be8a361e2b633d716bffc7c7104a3cc.jpg" alt="Matisse Android 图片选择器" width="550" height="381"></p>    <p>知乎 App 是支持日夜间模式的,因此 Matisse 也需要具备这个功能。但是作为一个开源库,不能依赖主 App 的日夜间模式的实现,我们为 Matisse 内置了两套主题,蓝色的 Zhihu 主题和暗色的 Dracula 主题。它们是通过先定义一套自定义属性,再在此基础上各自定义一个 theme,在创建图片选择器 Activity 的时候,应用这个 theme。如果两套内置主题不能满足你的需求,你也可以定义自己的 theme。</p>    <p>Matisse 的调用非常简单,使用了 Builder 模式,只需要在调用的时候传入想要的参数,后续的事情就不用你操心了。一个调用的例子如下:</p>    <pre>  <code class="language-java">Matisse  .from(MainActivity.this)  .choose(MimeType.of(MimeType.JPEG, MimeType.PNG, MimeType.GIF))  .countable(true)  .maxSelectable(9)  .addFilter(new GifSizeFilter(320, 320, 5 * Filter.K * Filter.K))  .gridExpectedSize(getResources()  .getDimensionPixelSize(R.dimen.grid_expected_size))  .restrictOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)  .thumbnailScale(0.85f)  .imageEngine(new GlideEngine())  .forResult(REQUEST_CODE_CHOOSE);</code></pre>    <p>通过上面的调用示例,你应该也可以猜到我们的接口大致有哪些功能:</p>    <ul>     <li> <p>支持包括 JPEG, PNG, GIF 图片类型的选择。后面可能还会支持视频内容的选择;</p> </li>     <li> <p>支持有序选择图片,也即选择图片的时候会有 1, 2, 3, 4… 样式的 CheckBox;</p> </li>     <li> <p>支持指定最大可选数量;</p> </li>     <li> <p>支持定义筛选规则,你可以针对特定图片类型集合,制定完全自定义的筛选规则;</p> </li>     <li> <p>可以定义图片缩略图的缩放比例。缩放比例越大,缩略图越清晰,但是列表滑动的时候,缩略图的加载也相应比较慢;</p> </li>     <li> <p>支持横竖屏。Matisse 做了状态保存的工作,因此不需要担心应用 configuration 变化带来的困扰,包括横竖屏的转换;</p> </li>     <li>支持不同的图片加载库,目前支持 Glide 和 Picasso。如果 Glide 和 Picasso 都不是你需要的,可以通过实现一个图片加载接口,定义自己的图片加载引擎。很抱歉,我们暂时不支持 Fresco。</li>    </ul>    <p>在数据加载方面,我们使用 Loader 作为相册和相册图片数据的加载机制,它可以很方便地异步获取系统 MediaStore 中的图片数据,只需定义好回调接口,数据就会自动返回到 UI 线程上。同时,在应用 configuration 改变的时候,页面可以重新连接上之前的 Loader,无需重新查询数据。如果你没用过 Loader,可以回忆一下 AsyncTask,它们用起来的感觉差不多,只不过 Loader 是一个更加强大的异步加载框架。对 Loader 感兴趣的同学可以参考官方的文档 <a href="/misc/goto?guid=4959748731462185381" rel="nofollow,noindex"> Loaders </a> 。</p>    <p>我们并没有采用 MV* 这些帮助代码实现分层解耦的架构,也尽量避免加入过多的第三方库的依赖。获取图片数据并进行展示是一件略繁琐的事情,因此这个库的代码并不是十分优雅。但是 Matisse 为你屏蔽了这些繁琐的逻辑和界面展示的细节,你要做的只是添加依赖,并通过几行代码进行调用即可。</p>    <p>Matisse 简单易用,可以满足你对于图片选择的基本需求。我们已经在知乎 Android App 内使用了 Matisse,也在 GitHub 上开源了它,感兴趣的同学可以看一下源码 <a href="/misc/goto?guid=4959748731546942659" rel="nofollow,noindex"> zhihu/Matisse </a> ,想吐槽或者提 bug 的可以提 issue,觉得有写的不好的地方,或希望添加新功能,也欢迎提 PR。</p>    <p>最后,感谢设计师@郑英伟。</p>    <p>Henri Matisse 是一位法国画家,野兽派的创始人及主要代表人物,也是一位雕塑家及版画家。 —— <a href="/misc/goto?guid=4959748731630833444" rel="nofollow,noindex"> 维基百科 - 亨利·马蒂斯 </a></p>    <p> </p>    <p>来自:https://zhuanlan.zhihu.com/p/26420284</p>    <p> </p>